Esta es una implementación de C ++ (11) del Protocolo seguro de flujo de medios en tiempo real (RTMFP) como se describe en RFC 7016.
La biblioteca incluye adaptadores de plataforma de muestra y otras utilidades, como un bucle de ejecución de select() , pero no se requiere que se usen. La implementación del protocolo está destinada a ser adaptable a cualquier entorno del programa host.
La biblioteca está destinada a clientes, servidores y aplicaciones P2P. Incluye los ayudantes necesarios y los ganchos de devolución de llamada para admitir la introducción de P2P y el equilibrio de carga.
El directorio test incluye pruebas y ejemplos unitarios. De una nota especial son tcserver , un servidor de medios RTMFP y RTMP Live RTMP; tcrelay , un RTMFP ↔︎ RTMP Relay/Proxy; y redirector , un simple equilibrador de carga.
La documentación de API más completa se encuentra actualmente en el archivo de encabezado rtmfp.hpp .
Una aplicación instanciará un IPlatformAdapter y un ICryptoAdapter , luego un com::zenomt::rtmfp::RTMFP (que requiere estos adaptadores). Por lo general, el adaptador de la plataforma deberá informarse de la nueva instancia RTMFP para que pueda invocar los métodos de la plataforma de la instancia (como howLongToSleep() y onReceivePacket() ).
La plataforma agregará al menos una interfaz llamando RTMFP::addInterface() .
La aplicación puede abrir flujos de envío a puntos finales nuevos o actuales con RTMFP::openFlow() y Flow::openFlow , y puede abrir flujos de retorno asociados con RecvFlow::openReturnFlow() .
La aplicación puede aceptar nuevos flujos estableciendo las devoluciones de llamada onRecvFlow en el RTMFP (para flujos entrantes desnudos) o en SendFlow S (para flujos de retorno asociados).
La aplicación puede enviar mensajes a pares lejanos con SendFlow::write() y recibir mensajes de pares lejanos estableciendo la devolución de llamada onMessage en RecvFlow s. Los mensajes pueden caducar y ser abandonados si no se inician o se entregan mediante plazos por mensaje, o por la lógica de aplicación arbitraria utilizando el WriteReceipt devuelto por SendFlow::write() . La solicitud puede ser notificada por devolución de llamada cuando se entrega o abandona un mensaje.
SendFlow s establecido en prioridad/precedencia PRI_PRIORITY , PRI_IMMEDIATE , PRI_FLASH o PRI_FLASHOVERRIDE se consideran críticos en el tiempo. Enviar mensajes críticos de tiempo afecta el control de congestión.
Cuando esté hecho, la aplicación puede apagar el RTMFP de manera ordenada o abruptamente.
La implementación del protocolo es de un solo hilo y no tiene bloqueos/mutexes. Todas las llamadas a sus API deben estar sincronizadas externamente, por ejemplo, por todas en el mismo hilo o construcción de bucle de ejecución. Esto se hizo para mejorar la portabilidad y el rendimiento, ya que el bloqueo puede ser muy costoso en las CPU modernas. La sincronización se abstrae por el método perform del adaptador de la plataforma para permitir la descarga de algunas operaciones costosas o que requieren mucho tiempo a otros núcleos/hilos, si lo desea.
La implementación del protocolo no interactúa directamente con los enchufes UDP del sistema operativo, reloj, bucles de ejecución, bloqueos o hilos. Estas interacciones se abstraen a un adaptador de plataforma proporcionado por el programa host.
El adaptador de la plataforma será una implementación concreta de com::zenomt::rtmfp::IPlatformAdapter , que llama a los métodos de instancia pública RTMFP en su sección "utilizado por el adaptador de plataforma". El adaptador proporciona la hora actual, la lectura y la escritura en los enchufes, el tiempo y la sincronización.
La biblioteca proporciona dos adaptadores de plataforma de ejemplo que se ejecutan en RunLoop S: PosixPlatformAdapter para aplicaciones puras de un solo subproceso, y PerformerPosixPlatformAdapter para permitir la descarga de criptografía de clave pública intensiva en CPU a un hilo de trabajadores. Estos adaptadores de plataforma deben ser adecuados para muchas aplicaciones en sistemas operativos similares a UNIX y deben servir como ejemplos de cómo escribir adaptadores de plataforma de un solo subproceso y múltiples para su aplicación de host.
No hay ningún requisito para que las interfaces del adaptador de la plataforma sean enchufes UDP. Por ejemplo, una interfaz podría ser calcetines o girar proxy, túnel o simulador de red.
Para sistemas operativos similares a UNIX, esta biblioteca proporciona un bucle de ejecución de select() adecuado para muchas aplicaciones basadas en sockets. También incluye un bucle de ejecución de epoll para Linux que escala mejor que select() para manejar muchos enchufes. Use el alias PreferredRunLoop para elegir automáticamente la mejor variante disponible en el momento de la compilación para el sistema operativo objetivo.
Se puede conectar un Performer a un bucle de ejecución para habilitar invocar una tarea dentro/sincronizada con el bucle de ejecución desde cualquier hilo. Los Performer se utilizan con el PerformerPosixPlatformAdapter .
Microsoft Windows no es una plataforma oficialmente compatible. Sin embargo, la biblioteca central (excluyendo los adaptadores de la plataforma, los bucles de ejecución y Performer ) debe basarse en Windows, y el mantenimiento del núcleo para esa plataforma se intentará a medida que lo permita el tiempo y la ayuda de la comunidad. Abra un problema si hay un problema con la biblioteca principal en Windows.
Para usar esta biblioteca en Windows, deberá proporcionar un adaptador de plataforma apropiado.
Póngase en contacto con el mantenedor o abra un problema para solicitar un enlace al adaptador de la plataforma de Windows que se agregará aquí en este documento.
RFC 7016 describe un marco generalizado para asegurar la comunicación RTMFP de acuerdo con las necesidades de la aplicación, y deja detalles criptográficos a un perfil de criptografía . Esta biblioteca no bloquea su aplicación en ningún perfil de criptografía en particular, y está escrita para respaldar muchos perfiles potenciales. El perfil de criptografía es implementado por un ICryptoAdapter concreto que se proporciona al RTMFP en instanciación.
La mayoría de las aplicaciones de RTMFP utilizarán el perfil de criptografía para la comunicación flash descrita en RFC 7425. Esto es proporcionado por FlashCryptoAdapter . Tenga en cuenta que este adaptador es abstracto y debe ser subclase para proporcionar implementaciones concretas de las primitivas criptográficas requeridas. FlashCryptoAdapter_OpenSSL proporciona una implementación concreta que usa OpenSSL, que también puede servir como un ejemplo de cómo usar otras bibliotecas de criptografía. Si no tiene OpenSSL o no desea usarlo, puede suprimir la construcción de este módulo definiendo make Variable WITHOUT_OPENSSL . Si su OpenSSL se instala fuera de las rutas de búsqueda predeterminadas de su compilador y de búsqueda de enlazador, puede definir make variables OPENSSL_INCLUDEDIR y OPENSSL_LIBDIR con las directivas apropiadas (consulte The Makefile para ver ejemplos).
La implementación OpenSSL del FlashCryptoAdapter implementa el Grupo 16 de intercambio de claves de Internet de 4096 bits (IKE) Group 16, 2048 bits Ike Group 14 e 1024 bits IKE Group 2 para el acuerdo de clave Diffie-Hellman. Todas las implementaciones del perfil de criptografía de comunicación Flash deben implementar al menos el grupo 2; Algunos también implementan el Grupo 14. Esta implementación prefiere el grupo común más fuerte.
Tenga en cuenta que RTMFP no se limita a la comunicación de la plataforma Flash. Esta biblioteca proporciona un PlainCryptoAdapter adecuado para pruebas y evaluaciones. Como no proporciona criptografía real (y sus métodos cryptoHash256() y pseudoRandomBytes() son especialmente débiles), no es adecuado para el uso de producción en Internet abierto. No.
Bufferbloat (búfer y cola excesiva en la red) puede causar retrasos de extremo a extremo, lo que resulta en un rendimiento inaceptable para aplicaciones en tiempo real. Desafortunadamente, la mejor solución a este problema (gestión de colas activas con notificación de congestión explícita) no se implementa universalmente en Internet en este momento.
Además de las señales de congestión normales (pérdida y notificación de congestión explícita), esta biblioteca puede inferir opcionalmente una congestión probable en una sesión por aumentos en el tiempo de ida y vuelta (RTT). Para habilitar esta capacidad, use Flow::setSessionCongestionDelay() para establecer una cantidad de retraso adicional por encima del RTT de referencia para ser interpretado como una indicación de congestión. El valor predeterminado es INFINITY . Se sugiere un valor de 0.1 segundos de retraso adicional para esta característica.
El RTT de línea de base es el RTT mínimo observado en la mayoría de los últimos tres minutos. La ventana de observación RTT de referencia se borra y se restablece en las siguientes circunstancias:
De vez en cuando, si se utiliza una porción significativa de la ventana de congestión, la ventana de congestión se reducirá temporalmente para sondear la ruta para una nueva RTT de línea de base (en caso de que nuestro propio envío esté enmascarando la línea de base). Tenga en cuenta que esto puede causar famosos.
Si se observa que el RTT suavizado está por encima de la línea de base más el CongestionDelay configurado (y también es de al menos 30 ms), se supone que esto es una indicación de congestión. El controlador de congestión responde a esto como si fuera una pérdida.
Este esquema de detección de congestión, como todos los basados en retrasos de extremo a extremo, es imperfecto y está sujeto a señales falsas positivas causadas por casos que incluyen:
Como tal, esta característica puede no estar indicada para todos los casos de uso. Se debe tener cuidado para habilitar esta función solo cuando las señales de congestión falsas positivas son poco probables, como para la transmisión de medios sustancialmente unidireccional a través de un cuello de botella dedicado. Los falsos positivos pueden causar el inanición de la transmisión.
Esta característica se inspira en el transporte de fondo de baja retraso adicional (LEDBAT), la adaptación de la tasa autoglocada para multimedia (Scream) y el algoritmo de control de congestión BBR de Google.
Esta implementación de RTMFP agrega soporte para una notificación de congestión explícita (ECN). Agrega un nuevo "Informe ECN" de la fragmentación experimental (tipo 0xec ) para que el receptor envíe los recuentos de puntos de código ECN recibidos al remitente ECN. Un RTMFP no debe enviar un informe ECN a su par a menos que haya recibido al menos un paquete válido en su sesión S_OPEN con ese par que está marcado con un punto de código de transporte capaz de ECN ( ECT(0) , ECT(1) o ECN-CE ).
Un receptor RTMFP que tiene capacidad para ECN envía informes ECN a su par con capacidad para ECN. Los informes de ECN deben ensamblarse antes de la primera fragmentación de reconocimiento en cualquier paquete que contenga un reconocimiento (para evitar el truncamiento del informe). Para que el remitente ECN pueda detectar si las interfaces cercanas y lejanas, la ruta y el soporte del receptor ECN, un receptor con capacidad de ECN debe enviar un informe ECN en cualquier paquete que contenga un reconocimiento, si se ha recibido algún paquete marcado con un punto de código de transporte capaz de ECN desde la última vez que se envió un informe ECN o si aún no se ha enviado un informe.
Un remitente RTMFP debe dejar de marcar los paquetes con puntos de código de transporte capaces de ECN si determina que el receptor no es con capacidad para ECN (por ejemplo, si el remitente no ha recibido al menos un informe ECN junto con un reconocimiento de los datos del usuario que se enviaron en un paquete marcado durante la sesión abierta con el Peer).
Un receptor RTMFP con capacidad para ECN mantiene al menos un recuento del número de paquetes recibidos marcados con ECN-CE . El punto final envía los 8 bits bajos del contador actual a su par en los trozos de informe ECN.
Esta implementación envía ECT(0) . El controlador de congestión responde a los aumentos del ECN-CE-count como si fuera la pérdida. ECT(0) solo se envía en paquetes que contienen datos del usuario.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0xec | 1 | ECN-CE-count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
struct ecnReportChunkPayload_t
{
uint8_t congestionExperiencedCountMod256; // ECN-CE-count
} :8;
congestionExperiencedCountMod256 : Los 8 bits bajos del recuento de paquetes recibidos del par marcado con ECN-CE (congestión ECN experimentada).