O quê?
O RTCQuicTransport é uma nova API de plataforma da Web que permite a troca de dados arbitrários com pares remotos usando o protocolo QUIC. Ele é destinado a casos de uso de peer a peer e, portanto, é usado com uma API RTCIceTransport independente para estabelecer uma conexão peer a peer usando ICE. Os dados são transportados de forma confiável e ordenada. Consulte a seção abaixo para saber mais sobre a entrega não ordenada e não confiável. Como é um transporte de dados genérico e bidirecional, ele pode ser usado para jogos, transferências de arquivos, transporte de mídia, mensagens etc.
Por quê?
Uma API de transporte de dados de baixo nível poderosa pode permitir que aplicativos (como comunicações em tempo real) façam coisas novas na Web. É possível criar com base na API, criando suas próprias soluções, ultrapassando os limites do que pode ser feito com conexões peer-to-peer, por exemplo, desbloqueando botões de alocação de taxa de bits personalizados. No futuro, mais suporte para mídia codificada poderá permitir a criação do próprio aplicativo de comunicação por vídeo com controles de baixo nível. O esforço do NV do WebRTC é migrar para APIs de nível mais baixo, e experimentar isso com antecedência é valioso.
Por que usar o QUIC?
O protocolo QUIC é desejável para comunicações em tempo real. Ele é baseado no
UDP, tem criptografia integrada, controle de congestionamento e é multiplexado sem
bloqueio de head-of-line. O RTCQuicTransport
oferece recursos muito semelhantes aos
da API RTCDataChannel
, mas usa o QUIC em vez do SCTP como protocolo de
transporte. Como a RTCQuicTransport
é uma API independente, ela não tem
a sobrecarga da API RTCPeerConnection
, que inclui a pilha de mídia em tempo real.
Como?
Visão geral da API
A API tem três abstrações principais: RTCIceTransport
, RTCQuicTransport
e RTCQuicStream
.
RTCIceTransport
O ICE é um protocolo para estabelecer conexões ponto a ponto pela Internet e
é usado no WebRTC atualmente. Esse objeto fornece uma API independente para estabelecer
uma conexão ICE. Ele é usado como o transporte de pacotes para a conexão QUIC,
e o RTCQuicTransport
o leva no construtor.
RTCQuicTransport
Representa uma conexão QUIC. Ele é usado para estabelecer uma conexão QUIC e criar streams QUIC. Ele também expõe estatísticas relevantes para o nível de conexão QUIC.
RTCQuicStream
Usado para ler e gravar dados no/do lado remoto. Os streams transportam
dados de forma confiável e ordenada. Vários streams podem ser criados a partir do mesmo
RTCQuicTransport
, e, quando os dados são gravados em um stream, um
evento "onquicstream" é acionado no transporte remoto. Os streams oferecem uma maneira de
distinguir dados diferentes na mesma conexão QUIC. Exemplos comuns podem
ser o envio de arquivos separados em streams separados, pequenos pedaços de dados em
streams diferentes ou diferentes tipos de mídia em streams separados.
RTCQuicStream
s são leves, são multiplexados em uma conexão QUIC e
não causam bloqueio de cabeça de linha para outros RTCQuicStream
s.
Configuração da conexão
Confira a seguir um exemplo de configuração de uma conexão QUIC ponto a ponto.
Assim como a RTCPeerConnection
, a API RTCQuicTransport
exige o uso de um
canal de sinalização seguro para negociar os parâmetros da conexão,
incluindo os parâmetros de segurança. O RTCIceTransport
negocia os parâmetros
ICE (ufrag e senha), bem como RTCIceCandidate
s.
Perspectiva do cliente:
const iceTransport = new RTCIceTransport();
const quicTransport = new RTCQuicTransport(iceTransport);
// Signal parameters, key and candidates.
signalingChannel.send({
iceParams: iceTransport.getLocalParameters(),
quicKey: quicTransport.getKey(),
});
iceTransport.onicecandidate = e => {
if (e.candidate) {
signalingChannel.send({candidate: e.candidate});
}
};
// When remote parameters are signaled, start connection.
signalingChannel.onMessage = async ({iceParams, candidate}) => {
if (iceParams) {
iceTransport.start(iceParams);
quicTransport.connect();
} else if (candidate) {
iceTransport.addRemoteCandidate(candidate);
}
};
Perspectiva do servidor:
const iceTransport = new RTCIceTransport();
const quicTransport = new RTCQuicTransport(iceTransport);
// Signal parameters, key and candidates.
signalingChannel.send({
iceParams: iceTransport.getLocalParameters(),
});
iceTransport.onicecandidate = e => {
if (e.candidate) {
signalingChannel.send({candidate: e.candidate});
}
};
// When remote parameters are signaled, start connection.
signalingChannel.onMessage = async ({iceParams, quicKey, candidate}) => {
if (iceParams && quicKey) {
iceTransport.start(iceParams);
quicTransport.listen(quicKey);
} else if (candidate) {
iceTransport.addRemoteCandidate(candidate);
}
};
Transferência de dados
A transferência de dados pode ser feita usando as APIs RTCQuicStream para leitura e gravação:
RTCQuicStreamReadResult readInto(Uint8Array data);
void write(RTCQuicStreamWriteParameters data);
Promise<void> waitForWriteBufferedAmountBelow(unsigned long amount);
Promise<void> waitForReadable(unsigned long amount);
Armazenamento em buffer
As promessas retornadas pelos métodos waitFor*
permitem armazenar dados em buffer quando
o JavaScript está ocupado. A pressão de retorno é aplicada ao lado de envio quando o
buffer de leitura fica cheio no lado de recebimento. O lado de envio tem um buffer de gravação
que pode ser preenchido quando a pressão reversa é aplicada. Portanto, o lado de gravação também tem um método waitForWriteBufferedAmountBelow
para
permitir a espera por espaço no buffer para gravar. Mais informações sobre
como gravar/ler dados podem ser encontradas na documentação
para desenvolvedores.
Entrega não solicitada/não confiável
Embora um RTCQuicStream
só ofereça suporte ao envio de dados de forma confiável e ordenada,
a entrega não confiável/não ordenada pode ser alcançada por outros meios. Para
entrega não ordenada, é possível enviar pequenos pedaços de dados em fluxos separados,
porque os dados não são ordenados entre os fluxos. Para entrega não confiável, é possível
enviar pequenos pedaços de dados com a flag "finish" definida como "true", seguida de uma chamada
reset()
no stream após um tempo limite. O tempo limite precisa depender de
quantas retransmissões são necessárias antes de descartar os dados.
Quando?
O teste de origem vai começar na versão 73 do Chrome e vai estar disponível até a versão M75. Depois disso, o teste de origem vai terminar. Com base no feedback e no interesse, vamos fazer as mudanças adequadas e enviar a API, continuar com um novo teste de origem ou descontinuar a API.
Onde?
Navegador Chrome em todas as plataformas, exceto iOS.
O que mais?
Feedback
Um dos principais objetivos do teste de origem é receber feedback de você, os desenvolvedores. Estamos interessados em:
- O que essa API permite?
- Como essa API melhora outras APIs de transporte de dados
(
WebSocket
s ouRTCDataChannel
s do WebRTC)? Como ela pode melhorar? - Desempenho
- Ergonomia da API
Inscrever-se no teste de origem
- Solicite um token para sua origem.
- Adicione o token às suas páginas. Há duas maneiras de fornecer esse token em
qualquer página na origem:
- Adicione uma tag
<meta>
origin-trial
ao cabeçalho de qualquer página. Por exemplo, ele pode ser parecido com este:<meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">
- Se for possível configurar o servidor, você também poderá fornecer o token nas páginas
usando um cabeçalho HTTP
Origin-Trial
. O cabeçalho de resposta resultante vai parecer mais ou menos assim:Origin-Trial: TOKEN_GOES_HERE
- Adicione uma tag
Especificação da Web
O rascunho de especificação avançou na API no teste de origem, incluindo:
- Transmissões unidirecionais mais alinhadas com as transmissões do WHATWG
- Como desativar as retransmissões
- Datagramas (em breve)
Temos interesse em implementar a especificação completa e além (incluindo suporte a transmissão do WHATWG), mas queremos ouvir seu feedback primeiro.
Segurança
A segurança no handshake QUIC é aplicada pelo uso de uma chave pré-compartilhada para estabelecer uma conexão P2P QUIC criptografada. Essa chave precisa ser sinalizada em um canal seguro fora da banda com garantias de confidencialidade e integridade. A chave será exposta ao JavaScript.
Ataque ativo
Ao contrário do DTLS-SRTP, que exige apenas integridade para sinalizar a impressão digital do certificado, a sinalização da chave pré-compartilhada exige integridade e confidencialidade. Se o PSK for comprometido (por exemplo, pelo servidor no canal de sinalização), um invasor ativo poderá montar um ataque man-in-the-middle contra o handshake do QUIC.
Status atual
Etapa | Status |
---|---|
1. Criar uma explicação | Concluído |
**2a. Especificação do RTCQuicTransport ** | **Em andamento** |
**2b. Especificação do RTCIceTransport ** | **Em andamento** |
**3. Coletar feedback e iterar o design** | **Em andamento** |
4. Teste de origem | Começa no Chrome 73. |
5. Lançamento | Não iniciado |
Links úteis
- Outra documentação
- Explicação para o público
- Rastreamento de bugs
- Solicitar um token de teste de origem
- Como usar um token de teste de origem
- Discussão sobre problemas para RTCQuicTransport
- Discussão sobre problemas para RTCIceTransport