Componentes de Cliente e Servidor QUIC para Delphi e C++ Builder | Blog eSeGeCe

Componentes de Cliente e Servidor QUIC para Delphi e C++ Builder

· Componentes
Componentes de cliente e servidor QUIC do sgcQUIC

sgcQUIC leva o protocolo de transporte QUIC (RFC 9000) para Delphi, C++ Builder e .NET. Ele traz dois novos componentes, TsgcQUICClient e TsgcQUICServer, ambos construídos sobre o mecanismo QUIC nativo do OpenSSL 3.5, de modo que o transporte e o handshake TLS 1.3 são executados como um único fluxo.

O QUIC é o protocolo por baixo do HTTP/3, mas é útil por si só. Ele funciona sobre UDP, multiplexa muitos streams independentes em uma única conexão, retoma com 0-RTT e sobrevive a uma troca de rede graças à migração de conexão. Este post aborda a camada QUIC bruta. O próximo post aborda os componentes HTTP/3 que ficam por cima.

Por que QUIC

Uma conexão clássica de TLS sobre TCP precisa de um handshake TCP e depois de um handshake TLS antes que o primeiro byte de dados da aplicação seja transmitido. O QUIC combina os dois em uma única troca, de modo que uma nova conexão fica pronta em um único round trip, e uma conexão retomada pode enviar dados com 0-RTT.

Como cada stream QUIC é entregue de forma independente, um pacote perdido em um stream não trava os demais. Isso elimina o bloqueio de cabeça de linha (head-of-line blocking) que ocorre quando você multiplexa sobre um único socket TCP. Uma conexão QUIC é identificada por um ID de conexão em vez do par de IP e porta, de modo que ela pode migrar do Wi-Fi para os dados móveis sem cair.

O Cliente QUIC

Defina Host e Port, atribua os eventos e então defina Active como True. O handshake é concluído em um único fluxo, e WriteData envia bytes em um stream QUIC.

uses
  sgcQUIC_Client;

var
  oClient: TsgcQUICClient;
begin
  oClient := TsgcQUICClient.Create(nil);
  oClient.Host := 'www.example.com';
  oClient.Port := 443;
  oClient.OnQUICConnect    := OnQUICConnect;
  oClient.OnQUICStreamData := OnQUICStreamData;
  oClient.OnQUICDisconnect := OnQUICDisconnect;

  oClient.Active := True;          // TLS 1.3 handshake in a single flight
  oClient.WriteData('ping');       // send bytes on a QUIC stream
end;

Os bytes recebidos chegam no evento OnQUICStreamData, que informa o id do stream e o payload:

procedure TForm1.OnQUICStreamData(Sender: TObject; aStreamId: Int64;
  aUnidirectional: Boolean; const aData: TBytes);
begin
  Memo1.Lines.Add('stream ' + IntToStr(aStreamId) + ': ' +
    TEncoding.UTF8.GetString(aData));
end;

O Servidor QUIC

O servidor escuta em uma porta UDP e precisa de um certificado e de uma chave privada no formato PEM. O QUIC sempre roda sobre TLS 1.3, portanto o certificado é obrigatório. Os bytes do cliente chegam em OnQUICData, e você responde com WriteData, passando a conexão que deseja responder.

uses
  sgcQUIC_Server;

var
  oServer: TsgcQUICServer;
begin
  oServer := TsgcQUICServer.Create(nil);
  oServer.Port := 443;
  oServer.QUICOptions.SSLOptions.CertFile := 'cert.pem';
  oServer.QUICOptions.SSLOptions.KeyFile  := 'key.pem';
  oServer.OnQUICConnect := OnQUICConnect;
  oServer.OnQUICData    := OnQUICData;
  oServer.Active := True;
end;

procedure TForm1.OnQUICData(Sender: TObject;
  aConnection: TsgcQUICServerConnection; const aData: TBytes);
begin
  // echo the message back to the client that sent it
  oServer.WriteData(aConnection, aData);
end;

Streams Multiplexados

Uma única conexão QUIC pode transportar muitos streams ao mesmo tempo. Chame EnableMultiStream antes de se conectar e então abra quantos streams precisar. Um stream bidirecional transporta uma requisição e sua resposta; um stream unidirecional envia dados em um só sentido.

oClient.EnableMultiStream;
oClient.OpenStream;                 // a new bidirectional stream
oClient.OpenStream(True);           // a unidirectional stream

O modo multi-stream usa o mecanismo QUIC embutido do OpenSSL 3.5. Cada stream tem seu próprio controle de fluxo, de modo que um stream lento ou travado nunca bloqueia os demais.

0-RTT e Migração de Conexão

Após um primeiro handshake bem-sucedido, o cliente pode guardar o session ticket e reconectar com 0-RTT, enviando dados da aplicação já no primeiro pacote. A migração de conexão mantém uma sessão viva durante uma troca de rede, o que é importante para clientes móveis que alternam entre Wi-Fi e rede celular. Ambos são tratados pelo mecanismo QUIC subjacente.

Disponibilidade

O sgcQUIC é um pacote separado, licenciado como um add-on do sgcWebSockets Enterprise. Toda licença inclui o código-fonte Pascal completo e um ano de atualizações. Os componentes são instalados na paleta SGC QUIC e oferecem suporte a Delphi e C++ Builder 7 até 13, além de uma versão .NET com os mesmos nomes de classe Tsgc.

Os componentes de cliente e servidor HTTP/3 são abordados em o próximo post. Você pode baixar a versão trial e ler a referência completa dos componentes na página do produto sgcQUIC.

Dúvidas ou feedback? Entre em contato, você receberá uma resposta das pessoas que escreveram o código.