Esta é uma implementação C ++ (11) do Protocolo de Fluxo de Mídia em tempo real (RTMFP) seguro, conforme descrito no RFC 7016.
A biblioteca inclui adaptadores de plataforma de amostra e outros utilitários, como um loop de execução simples select() , mas não precisam ser usados. A implementação do protocolo deve ser adaptável a qualquer ambiente do programa host.
A biblioteca se destina a clientes, servidores e aplicativos P2P. Inclui os ajudantes necessários e os ganchos de retorno de chamada para apoiar a introdução do P2P e o balanceamento de carga.
O diretório test inclui testes de unidade e exemplos. De Nota Especial são tcserver , um servidor de mídia Live RTMFP e RTMP simples; tcrelay , um relé/proxy rtmfp ↔︎ rtmp; e redirector , um balanceador de carga simples.
A documentação da API mais completa está atualmente no arquivo de cabeçalho rtmfp.hpp .
Um aplicativo instanciará um IPlatformAdapter e um ICryptoAdapter , depois um com::zenomt::rtmfp::RTMFP (que requer esses adaptadores). Normalmente, o adaptador da plataforma precisará ser informado da nova instância RTMFP para que possa invocar os métodos da plataforma da instância (como howLongToSleep() e onReceivePacket() ).
A plataforma adicionará pelo menos uma interface chamando RTMFP::addInterface() .
O aplicativo pode abrir os fluxos de envio para pontos de extremidade novos ou atuais com RTMFP::openFlow() e Flow::openFlow , e pode abrir os fluxos de retorno associados com RecvFlow::openReturnFlow() .
O aplicativo pode aceitar novos fluxos, definindo os retornos de chamada onRecvFlow no RTMFP (para fluxos de entrada nus) ou no SendFlow s (para fluxos de retorno associados).
O aplicativo pode enviar mensagens para os colegas distantes com SendFlow::write() e receber mensagens de pares distantes, definindo o retorno de chamada onMessage no RecvFlow s. As mensagens podem expirar e ser abandonadas se não forem iniciadas ou entregues por prazos por mensagens, ou por lógica de aplicativo arbitrário usando o WriteReceipt S Retornado por SendFlow::write() . O aplicativo pode ser notificado por retorno de chamada quando uma mensagem é entregue ou abandonada.
O FLOWS SendFlow STIP como prioridade/precedência PRI_PRIORITY , PRI_IMMEDIATE , PRI_FLASH ou PRI_FLASHOVERRIDE são considerados tempo crítico. O envio de mensagens críticas de tempo afeta o controle de congestionamento.
Quando terminar, o aplicativo pode desligar o RTMFP de maneira ordenada ou abruptamente.
A implementação do protocolo é de thread única e não possui bloqueios/mutexes. Todas as chamadas para suas APIs devem ser sincronizadas externamente, por exemplo, por todos estarem no mesmo thread ou construção semelhante a um loop. Isso foi feito para melhorar a portabilidade e o desempenho, pois o bloqueio pode ser muito caro nas CPUs modernas. A sincronização é abstraída pelo método perform do adaptador da plataforma para permitir a descarga de algumas operações caras ou demoradas para outros núcleos/threads, se desejado.
A implementação do protocolo não interage diretamente com os soquetes UDP do sistema operacional, relógio, loops de execução, bloqueios ou threads. Essas interações são abstraídas para um adaptador de plataforma fornecido pelo programa host.
O adaptador da plataforma será uma implementação concreta do com::zenomt::rtmfp::IPlatformAdapter , que chama os métodos de instância pública RTMFP em sua seção "Usado pelo adaptador da plataforma". O adaptador fornece o horário atual, a leitura e a escrita para soquetes, tempo e sincronização.
A biblioteca fornece dois adaptadores de plataforma de exemplo que são executados em RunLoop S: PosixPlatformAdapter para aplicações puras de thread único, e PerformerPosixPlatformAdapter para permitir a descarga de criptografia de chave pública intensiva em CPU para um thread trabalhador. Esses adaptadores de plataforma devem ser adequados para muitos aplicativos em sistemas operacionais semelhantes ao UNIX e devem servir como exemplos de como escrever adaptadores de plataforma de thread e multithread para o seu aplicativo de host.
Não há exigência para que as interfaces do adaptador da plataforma sejam soquetes UDP. Por exemplo, uma interface pode ser uma meias ou proxy, túnel ou simulador de rede.
Para sistemas operacionais semelhantes ao UNIX, esta biblioteca fornece um loop de execução simples select() adequado para muitos aplicativos baseados em soquete. Ele também inclui um loop de corrida baseado em epoll simples para o Linux que escala melhor do que select() para lidar com muitos soquetes. Use o alias PreferredRunLoop para escolher automaticamente a melhor variante disponível no horário de compilação para o sistema operacional de destino.
Um Performer pode ser anexado a um loop de execução para permitir a invocação de uma tarefa dentro/sincronizada com o loop de execução de qualquer encadeamento. Performer S são usados com o PerformerPosixPlatformAdapter .
O Microsoft Windows não é uma plataforma oficialmente suportada. No entanto, a biblioteca principal (excluindo os adaptadores da plataforma, os loops de execução e Performer ) deve se basear no Windows, e a manutenção do núcleo para essa plataforma será tentada como o tempo e a ajuda da comunidade. Abra um problema se houver um problema com a biblioteca principal no Windows.
Para usar esta biblioteca no Windows, você precisará fornecer um adaptador de plataforma apropriado.
Entre em contato com o mantenedor ou abra um problema para solicitar um link para o adaptador do Windows Platform a ser adicionado aqui neste documento.
O RFC 7016 descreve uma estrutura generalizada para proteger a comunicação RTMFP de acordo com as necessidades do aplicativo e deixa especificações criptográficas para um perfil de criptografia . Esta biblioteca não bloqueia seu aplicativo em nenhum perfil de criptografia específica e está escrito para suportar muitos perfis em potencial. O perfil de criptografia é implementado por um ICryptoAdapter concreto fornecido ao RTMFP na instanciação.
A maioria das aplicações do RTMFP usará o perfil de criptografia para comunicação flash descrita no RFC 7425. Isso é fornecido pelo FlashCryptoAdapter . Observe que este adaptador é abstrato e deve ser subclassificado para fornecer implementações concretas das primitivas criptográficas necessárias. Uma implementação concreta usando o OpenSSL é fornecida pelo FlashCryptoAdapter_OpenSSL , que também pode servir de exemplo de como usar outras bibliotecas de criptografia. Se você não possui o OpenSSL ou não deseja usá -lo, pode suprimir a criação deste módulo definindo make Variable WITHOUT_OPENSSL . Se o seu OpenSSL estiver instalado fora do padrão do seu compilador, os caminhos de pesquisa de vinculadores, você poderá definir variáveis make OPENSSL_INCLUDEDIR e OPENSSL_LIBDIR com diretivas apropriadas (consulte o Makefile para exemplos).
A implementação do OpenSSL do FlashCryptoAdapter implementa o Grupo 16, o Grupo 16, o Grupo IKE 14 de 4096 bits da Internet (IKE) e o Grupo 2 IKE 2 de 2048 bits e o Diffie-Hellman Key Accord. Todas as implementações do perfil de criptografia de comunicação flash devem implementar pelo menos o grupo 2; Alguns também implementam o grupo 14. Esta implementação prefere o grupo comum mais forte.
Observe que o RTMFP não se limita à comunicação da plataforma flash. Esta biblioteca fornece um PlainCryptoAdapter adequado para teste e avaliação. Como não fornece criptografia real (e seus métodos cryptoHash256() e pseudoRandomBytes() são especialmente fracos), não é adequado para o uso da produção na Internet aberta. Não.
BufferBloat (buffer excessivo e fila na rede) pode causar atrasos de ponta a ponta, resultando em desempenho inaceitável para aplicativos em tempo real. Infelizmente, a melhor solução para esse problema (gerenciamento de filas ativo com notificação explícita de congestionamento) não é universalmente implantada na Internet neste momento.
Além dos sinais normais de congestionamento (perda de perda e notificação explícita de congestionamento), essa biblioteca pode opcionalmente inferir o provável congestionamento em uma sessão de aumentos no tempo de ida e volta (RTT). Para ativar esse recurso, use Flow::setSessionCongestionDelay() para definir uma quantidade de atraso adicional acima da RTT da linha de base para ser interpretada como uma indicação de congestionamento. O valor padrão é INFINITY . Um valor de 0.1 segundos de atraso adicional é sugerido para esse recurso.
A RTT da linha de base é a RTT mínima observada no máximo nos últimos três minutos. A janela de observação da RTT da linha de base é limpa e redefinida nas seguintes circunstâncias:
De tempos em tempos, se uma parte significativa da janela de congestionamento estiver sendo usada, a janela de congestionamento será temporariamente reduzida para investigar o caminho para um novo RTT de linha de base (caso nosso próprio envio esteja mascarando a linha de base). Observe que isso pode causar instabilidade.
Se a RTT suavizada for observada acima da linha de base mais o CongestionDelay configurado (e também é de pelo menos 30ms), supõe -se que isso seja uma indicação de congestionamento. O controlador de congestionamento responde a isso como se fosse uma perda.
Esse esquema de detecção de congestionamento, como todos os de ponta a ponta, é imperfeito e está sujeito a sinais de falsos positivos causados por casos, incluindo:
Como tal, esse recurso não pode ser indicado para todos os casos de uso. Deve -se tomar cuidado para permitir esse recurso apenas quando os sinais de congestionamento positivo são improváveis, como para a transmissão de mídia substancialmente unidirecional através de um gargalo dedicado. Os falsos positivos podem causar fome de transmissão.
Esse recurso é inspirado no transporte de fundo de baixo atraso extra (LEDBAT), adaptação de taxa auto-reclamada para multimídia (Scream) e algoritmo de controle de congestionamento BBR do Google.
Essa implementação do RTMFP adiciona suporte para notificação explícita de congestionamento (ECN). Ele adiciona um novo "Relatório ECN" Experimental (Tipo 0xec ) para o destinatário enviar contagens de pontos de codePePePs recebidos de volta ao remetente do ECN. Um RTMFP não deve enviar um relatório ECN para seu par, a menos que tenha recebido pelo menos um pacote válido em sua sessão S_OPEN com o par que está marcado com um ponto de código de transporte capaz de CEN ( ECT(0) , ECT(1) ou ECN-CE ).
Um receptor RTMFP com capacidade para o ECN envia relatórios de ECN para seu par de ECN. Os relatórios da ECN devem ser montados antes do primeiro pedaço de reconhecimento em qualquer pacote que contenha um reconhecimento (para evitar o truncamento do relatório). Para que o remetente da ECN possa detectar se as interfaces, caminho e suporte do receptor próximos e distantes, um receptor com capacidade para o ECN deve enviar um relatório de ECN em qualquer pacote que contenha um reconhecimento, se um pacote marcado com um relatório de CEN não foi enviado.
Um remetente RTMFP deve parar de marcar pacotes com pontos de código de transporte capaz de ECN se determinar que o receptor não será capaz de ser capaz (por exemplo, se o remetente não recebeu pelo menos um relatório da ECN junto com um reconhecimento de dados do usuário que foi enviado em um pacote marcado durante o aberto com o par).
Um receptor RTMFP com capacidade de ECN mantém pelo menos uma contagem do número de pacotes recebidos marcados com ECN-CE . O endpoint envia os 8 bits baixos do contador atual para seus pares no relatório ECN.
Esta implementação envia ECT(0) . O controlador de congestionamento responde a aumentos da ECN-CE-count como se fosse perda. ECT(0) é enviado apenas em pacotes contendo dados do usuário.
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 : Os 8 bits baixos da contagem de pacotes recebidos do par marcado com ECN-CE (congestionamento da ECN experimentado).