Componentes de cliente y servidor QUIC para Delphi y C++ Builder | Blog de eSeGeCe

Componentes de cliente y servidor QUIC para Delphi y C++ Builder

· Componentes
Componentes de cliente y servidor QUIC de sgcQUIC

sgcQUIC lleva el protocolo de transporte QUIC (RFC 9000) a Delphi, C++ Builder y .NET. Incluye dos nuevos componentes, TsgcQUICClient y TsgcQUICServer, ambos construidos sobre el motor QUIC nativo de OpenSSL 3.5, de modo que el transporte y el handshake de TLS 1.3 se ejecutan como un único intercambio.

QUIC es el protocolo que hay debajo de HTTP/3, pero resulta útil por sí mismo. Funciona sobre UDP, multiplexa muchos streams independientes en una sola conexión, se reanuda con 0-RTT y sobrevive a un cambio de red gracias a la migración de conexión. Esta entrada cubre la capa QUIC en bruto. La siguiente entrada cubre los componentes HTTP/3 que se sitúan encima.

Por qué QUIC

Una conexión clásica de TLS sobre TCP necesita un handshake de TCP y luego un handshake de TLS antes de que viaje el primer byte de datos de aplicación. QUIC combina ambos en un solo intercambio, de modo que una conexión nueva queda lista en un único viaje de ida y vuelta, y una reanudada puede enviar datos con 0-RTT.

Como cada stream QUIC se entrega de forma independiente, un paquete perdido en un stream no detiene a los demás. Eso elimina el bloqueo de cabecera de línea (head-of-line blocking) que se produce al multiplexar sobre un único socket TCP. Una conexión QUIC se identifica mediante un identificador de conexión (connection ID) en lugar de por el par de IP y puerto, por lo que puede migrar de Wi-Fi a datos móviles sin cortarse.

El cliente QUIC

Establece Host y Port, asigna los eventos y después pon Active en True. El handshake se completa en un solo intercambio, y WriteData envía bytes por un 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;

Los bytes entrantes llegan en el evento OnQUICStreamData, que informa del identificador de stream y de la carga útil:

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

El servidor QUIC

El servidor escucha en un puerto UDP y necesita un certificado y una clave privada en formato PEM. QUIC siempre se ejecuta sobre TLS 1.3, por lo que el certificado es obligatorio. Los bytes del cliente llegan en OnQUICData, y respondes con WriteData, pasando la conexión a la que quieres contestar.

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

Una sola conexión QUIC puede transportar muchos streams a la vez. Llama a EnableMultiStream antes de conectar y luego abre tantos streams como necesites. Un stream bidireccional transporta una petición y su respuesta; un stream unidireccional envía datos en un solo sentido.

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

El modo multi-stream utiliza el motor QUIC integrado de OpenSSL 3.5. Cada stream tiene su propio control de flujo, de modo que un stream lento o bloqueado nunca detiene a los demás.

0-RTT y migración de conexión

Tras un primer handshake correcto, el cliente puede conservar el ticket de sesión y reconectar con 0-RTT, enviando datos de aplicación en el primer paquete. La migración de conexión mantiene viva una sesión a través de un cambio de red, lo que importa para los clientes móviles que se mueven entre Wi-Fi y red celular. De ambas cosas se encarga el motor QUIC subyacente.

Disponibilidad

sgcQUIC es un paquete independiente, con licencia como complemento de sgcWebSockets Enterprise. Cada licencia incluye el código fuente completo en Pascal y un año de actualizaciones. Los componentes se instalan en la paleta SGC QUIC y son compatibles con Delphi y C++ Builder 7 hasta 13, además de un port a .NET con los mismos nombres de clase Tsgc.

Los componentes de cliente y servidor HTTP/3 se tratan en la siguiente entrada. Puedes descargar la versión de prueba y leer la referencia completa de los componentes en la página del producto sgcQUIC.

¿Preguntas o comentarios? Ponte en contacto, recibirás respuesta de las personas que escribieron el código.