TsgcHTTP3Server › Methods › TunnelSend
Sends bytes back on an established CONNECT tunnel stream.
procedure TunnelSend(const aConnection: TsgcQUICServerConnection; aStreamId: Int64; const aData: TBytes); virtual;
| Name | Type | Description |
|---|---|---|
aConnection | const TsgcQUICServerConnection | QUIC connection that owns the tunnel. Nothing is sent when this is nil. |
aStreamId | Int64 | Identifier of the CONNECT request stream that became the tunnel. Use the aStreamId reported by OnH3TunnelData. |
aData | const TBytes | Bytes to tunnel. They become the payload of a single DATA frame. An empty array sends nothing. |
TunnelSend is the write side of an HTTP/3 tunnel established with CONNECT, either the plain CONNECT method of RFC 9114 section 4.4 or the Extended CONNECT of RFC 9220. A CONNECT request that your OnH3Request handler answers with a 2xx status turns the request stream into a tunnel: the server keeps the stream open, stops treating incoming DATA frames as a request body and starts routing them to OnH3TunnelData. TunnelSend pushes bytes in the opposite direction, wrapping aData in a DATA frame on that same stream.
Bytes are sent exactly as supplied, with no framing of their own beyond the HTTP/3 DATA frame, so the tunneled protocol is entirely up to the application. There is no buffering or reassembly guarantee at the tunnel level either: a peer may read one TunnelSend call as several chunks, so a protocol carried over the tunnel needs its own message boundaries.
When the tunnel is on an additional request stream, the server writes to that specific QUIC stream. When it is on the connection's first (default) request stream, the write goes to the connection's default stream. Both cases are handled from the aStreamId you pass, so simply echoing back the id received from OnH3TunnelData is always correct.
This member is currently available in the Delphi/C++Builder implementation only.
// 1. accept the CONNECT so the stream becomes a tunnel
procedure OnH3RequestEvent(Sender: TObject; const aConnection:
TsgcQUICServerConnection; const aRequest: TsgcHTTP3Request;
const aResponse: TsgcHTTP3Response);
begin
if aRequest.Method = h3meConnect then
aResponse.StatusCode := 200 // 2xx establishes the tunnel
else
aResponse.StatusCode := 404;
end;
// 2. echo every byte that arrives on the tunnel back to the peer
procedure OnH3TunnelDataEvent(Sender: TObject; const aConnection:
TsgcQUICServerConnection; aStreamId: Int64; const aData: TBytes);
begin
TsgcHTTP3Server(Sender).TunnelSend(aConnection, aStreamId, aData);
end;