O quiche é uma implementação do Protocolo de Transporte Quic e HTTP/3, conforme especificado pelo IETF. Ele fornece uma API de baixo nível para processar pacotes QIC e manusear o estado de conexão. O aplicativo é responsável pelo fornecimento de E/S (por exemplo, manuseio de soquetes), bem como um loop de evento com suporte para temporizadores.
Para obter mais informações sobre como a quiche surgiu e algumas idéias sobre seu design, você pode ler um post no blog do Cloudflare que entra em mais detalhes.
Quiche Powers CloudFlare Edge HTTP/3 Support. O site CloudFlare-Quic.com pode ser usado para testes e experimentação.
O Resolver DNS do Android usa o quiche para implementar o DNS sobre o HTTP/3.
O quiche pode ser integrado ao CRO para fornecer suporte para HTTP/3.
O quiche pode ser integrado ao Nginx usando um patch não oficial para fornecer suporte para HTTP/3.
Antes de mergulhar na API de quiche, aqui estão alguns exemplos sobre como usar as ferramentas de quiche fornecidas como parte da caixa de quiche-apps.
Depois de clonar o projeto de acordo com o comando mencionado na seção de construção, o cliente pode ser executado da seguinte maneira:
$ cargo run-bin quiche-client-https://cloudflare-quic.com/
Enquanto o servidor pode ser executado da seguinte forma:
$ Cargo Run-Bin Quiche-Server---CERT APPS/SRC/BIN/CERT.CRT-APPS/SRC/BIN/CERT.KEY
(Observe que o certificado fornecido é auto-indeferido e não deve ser usado na produção)
Use o --help
-help de linha de comando para obter uma descrição mais detalhada das opções de cada ferramenta.
O primeiro passo para estabelecer uma conexão QIC usando o quiche é criar um objeto Config
:
Deixe Mut Config = quiche :: config :: new (quiche :: protocol_version)?
O objeto Config
controla aspectos importantes da conexão QIC, como versão QIC, IDs ALPN, controle de fluxo, controle de congestionamento, tempo limite ocioso e outras propriedades ou recursos.
O QIC é um protocolo de transporte de uso geral e existem várias propriedades de configuração em que não há valor padrão razoável. Por exemplo, o número permitido de fluxos simultâneos de qualquer tipo específico depende do aplicativo que executa o QIC e outras preocupações específicas do caso de uso.
A quiche padrão é várias propriedades para zero, os aplicativos provavelmente precisam defini -los para outra coisa para satisfazer suas necessidades usando o seguinte:
set_initial_max_streams_bidi()
set_initial_max_streams_uni()
set_initial_max_data()
set_initial_max_stream_data_bidi_local()
set_initial_max_stream_data_bidi_remote()
set_initial_max_stream_data_uni()
Config
também contém a configuração do TLS. Isso pode ser alterado pelos mutadores no objeto existente ou na construção de um contexto TLS manualmente e criando uma configuração usando with_boring_ssl_ctx_builder()
.
Um objeto de configuração pode ser compartilhado entre várias conexões.
No lado do cliente, a função utilitária connect()
pode ser usada para criar uma nova conexão, enquanto accept()
é para servidores:
// Connection.Let Conn. & mut config)?;
Usando o método recv()
da conexão, o aplicativo pode processar pacotes recebidos que pertencem a essa conexão da rede:
Seja para = soket.local_addr (). Unwrap (); loop {let (leia, de) = socket.recv_from (& mut buf) .unwrap (); let recv_info = quiche :: recvvinfo {de, para}; let = read = Combine Conn.recv (& mut buf [.. leia], recv_info) {ok (v) => v, err (e) => {// Ocorreu um erro, lidar com ele.break;},};}
O pacote de saída é gerado usando o método send()
da conexão::
loop {let (write, send_info) = combine Conn.send (& mut out) {ok (v) => v, err (quiche :: error :: done) => {// feito writing.break;}, err ( e) => {// Ocorreu um erro, lidar com ele.break;},}; soquete.send_to (& out [.. write], & send_info.to) .unwrap ();}
Quando os pacotes são enviados, o aplicativo é responsável por manter um cronômetro para reagir a eventos de conexão baseados no tempo. A expiração do timer pode ser obtida usando o método timeout()
da conexão.
deixe timeout = Conn.Timeout ();
O aplicativo é responsável por fornecer uma implementação do timer, que pode ser específica para o sistema operacional ou a estrutura de rede usada. Quando um timer expira, o método on_timeout()
da conexão deve ser chamado, após o qual pacotes adicionais podem precisar ser enviados na rede:
// Tempo limite expirou, manipulá -lo.conn.on_timeout (); // Envie mais pacotes conforme necessário após o timeout.loop {let (write, send_info) = combine Conn.send (& mut out) {ok (v) => v, Err (quiche :: error :: done) => {// feito writing.break;}, err (e) => {// Ocorreu um erro, alça it.break;},}; soquete.send_to (& out [.. write], & send_info.to) .unwrap ();}
Recomenda-se que os aplicativos sejam enviados de pacotes de saída para evitar a criação de rajadas de pacotes que possam causar congestionamento e perdas de curto prazo na rede.
O quiche expõe dicas de ritmo para pacotes de saída através do campo [ at
] da estrutura [ SendInfo
] que é retornada pelo método send()
. Este campo representa o tempo em que um pacote específico deve ser enviado para a rede.
Os aplicativos podem usar essas dicas, atrasando artificialmente o envio de pacotes por meio de mecanismos específicos da plataforma (como a opção SO_TXTIME
Socket no Linux) ou métodos personalizados (por exemplo, usando temporizadores de espaço do usuário).
Após alguns de um lado para o outro, a conexão concluirá seu aperto de mão e estará pronto para enviar ou receber dados do aplicativo.
Os dados podem ser enviados em um fluxo usando o método stream_send()
:
Se Conn.is_establed () {// handshake concluído, envie alguns dados no fluxo 0.conn.stream_send (0, b "hello", true)?;}
O aplicativo pode verificar se existem fluxos legíveis usando o método readable()
da conexão, que retorna um iterador sobre todos os fluxos que possuem dados pendentes para ler.
O método stream_recv()
pode ser usado para recuperar os dados do aplicativo do fluxo legível:
se conn.is_establed () {// iterar sobre streams. para stream_id em Conn.reablelable () {// stream é legível, leia até que não haja mais dados. (stream_id, & mut buf) {println! ("obtive {} bytes no fluxo {}", leia, stream_id);}}}
O módulo quiche HTTP/3 fornece uma API de alto nível para enviar e receber solicitações e respostas HTTP na parte superior do protocolo de transporte QIC.
Dê uma olhada no diretório [quiche/exemplos/] para obter exemplos mais completos sobre como usar a API de quiche, incluindo exemplos sobre como usar quiche em aplicativos C/C ++ (veja abaixo para obter mais informações).
O quiche expõe uma API f fina em cima da API da ferrugem que pode ser usada para integrar mais facilmente quiche em aplicações C/C ++ (bem como em outros idiomas que permitem chamar APIs C por alguma forma de FFI). A API C segue o mesmo design da ferrugem, módulo, as restrições impostas pela própria linguagem C.
Ao executar cargo build
, uma biblioteca estática chamada libquiche.a
será construída automaticamente ao lado do Rust One. Isso é totalmente independente e pode ser vinculado diretamente aos aplicativos C/C ++.
Observe que, para ativar a API da FFI, o recurso ffi
deve ser ativado (ele é desativado por padrão), passando --features ffi
para cargo
.
O quiche requer ferrugem 1,67 ou posterior para construir. A mais recente liberação estável de ferrugem pode ser instalada usando o Rustup.
Depois que o ambiente de construção da ferrugem é configurado, o código -fonte de quiche pode ser buscado usando o Git:
Clone $ Git -Recursiva https://github.com/cloudflare/quiche
e depois construído usando carga:
$ cargo build -examples
A carga também pode ser usada para executar o TestSuite:
$ teste de carga
Observe que o BoringsSL, usado para implementar o handshake de mão criptográfico do QIC com base no TLS, precisa ser construído e vinculado à quiche. Isso é feito automaticamente ao criar quiche usando carga, mas exige que o comando cmake
esteja disponível durante o processo de construção. No Windows, você também precisa de Nasm. A documentação oficial do BoringsSL tem mais detalhes.
Em alternativa, você pode usar sua própria construção personalizada do BoringsSL, configurando o diretório BoringsSL com a variável QUICHE_BSSL_PATH
ambiente:
$ Quiche_bssl_path = "/path/to/boringssl" Construção de carga -Exemplos
Como alternativa, você pode usar o OpenSSL/Quictls. Para permitir que o quiche use este fornecedor, o recurso openssl
pode ser adicionado à lista --feature
. Esteja ciente de que 0-RTT
não é suportado se esse fornecedor for usado.
Construir quiche para Android (versão 19 do NDK ou superior, 21 recomendado), pode ser feito usando cargo-ndk (v2.0 ou posterior).
Primeiro, o Android NDK precisa ser instalado, usando o Android Studio ou diretamente, e a variável de ambiente ANDROID_NDK_HOME
precisa ser definida para o caminho de instalação do NDK, por exemplo:
$ export android_ndk_home =/usr/local/share/android-ndk
Em seguida, a cadeia de ferramentas Rust para as arquiteturas Android necessária pode ser instalada da seguinte maneira:
$ Rustup Alvo ADD AARCH64-Linux-Android Armv7-Linuide-AndroideAbi I686-Linux-Android X86_64-Linux-Android
Observe que o nível mínimo da API é 21 para todas as arquiteturas -alvo.
Cargo-NDK (v2.0 ou mais tarde) também precisa ser instalado:
$ cargo install cargo-ndk
Finalmente, a biblioteca de quiche pode ser construída usando o seguinte procedimento. Observe que as opções -t <architecture>
e -p <NDK version>
são obrigatórias.
$ cargo ndk -t ARM64 -V8A -P 21 -Build -Romes FFI
Consulte Build_android_ndk19.sh para obter mais informações.
Para construir quiche para iOS, você precisa do seguinte:
Instale as ferramentas de linha de comando xcode. Você pode instalá -los com Xcode ou com o seguinte comando:
$ xcode-Select--Instalação
Instale o Rust Toolchain para arquiteturas iOS:
$ rustup alvo adicione aarch64-apple-Iios x86_64-apple-Iios
Instale cargo-lipo
:
$ Cargo Install Cargo-Lipo
Para construir Libquiche, execute o seguinte comando:
$ cargo lipo -FFI de recursos
ou
$ cargo lipo -Romadas FFI -Release
O iOS Build é testado no Xcode 10.1 e Xcode 11.2.
Para construir as imagens do Docker, basta executar o seguinte comando:
$ Make Docker-Build
Você pode encontrar as imagens do Docker de Quiche nos seguintes repositórios do Docker Hub:
Cloudflare/quiche
CloudFlare/Quiche-Qns
A tag latest
será atualizada sempre que as atualizações de ramificação Master Quiche.
Cloudflare/quiche
Fornece um servidor e cliente instalado em/usr/local/bin.
CloudFlare/Quiche-Qns
Fornece o script para testar o quiche dentro do corredor de interropia quic.
Copyright (c) 2018-2019, Cloudflare, Inc.
Veja a cópia da licença.