TsgcQUICServer › Events › OnQUICStreamData

OnQUICStreamData Event

Fires with bytes read from an additional QUIC stream, tagged with its stream id. Requires multi-stream mode.

Syntax

property OnQUICStreamData: TsgcQUICServerStreamDataEvent;
// TsgcQUICServerStreamDataEvent = procedure(Sender: TObject; const aConnection: TsgcQUICServerConnection; aStreamId: Int64; aUnidirectional: Boolean; const aData: TBytes) of object

Default Value

—

Parameters

NameTypeDescription
SenderTObjectThe TsgcQUICServer instance.
aConnectionconst TsgcQUICServerConnectionThe connection the stream belongs to. See TsgcQUICServerConnection. Call its FindStreamById with aStreamId to get a TsgcQUICServerStream you can write to.
aStreamIdInt64The QUIC stream id these bytes arrived on, or -1 if it could not be read. Use it to demultiplex, several streams on one connection interleave through this single event.
aUnidirectionalBooleanTrue when the stream is one-way, derived from bit 0x02 of the stream id. You cannot write back on a peer-opened unidirectional stream.
aDataconst TBytesThe chunk read on this pass. Not a message boundary, see the Remarks.

Remarks

This event is the multi-stream counterpart of OnQUICData. OnQUICData carries the connection's single default data stream, while OnQUICStreamData carries every other stream, each identified by aStreamId.

It only fires in multi-stream mode. Set AlwaysMultiStream to True, otherwise the server never accepts additional streams and this event stays silent.

The transport reads a stream only when the peer opened it, or when it is bidirectional. A unidirectional stream that the server opened with OpenStream is write-only and never reports here.

aData is whatever the read returned, not a framed message. A logical message may arrive across several calls, and streams interleave, so buffer per aStreamId and reassemble at the application level. When the peer concludes a stream, the transport drops it silently and the connection stays alive, there is no per-stream close event.

Do not assign this event on a TsgcHTTP3Server. That component sets AlwaysMultiStream and wires OnQUICStreamData to its own handler in its constructor, because HTTP/3 delivers the client's control and QPACK streams (RFC 9114) this way. Overwriting it breaks the HTTP/3 layer. Use the HTTP/3 events instead.

Unlike the other QUIC server events, OnQUICStreamData is public, not published, so it does not appear in the Object Inspector and must be assigned from code. It is primarily a transport hook for higher level protocols such as WebTransport.

This event runs on the server's background listener thread, so marshal to the main thread before touching the UI.

This member is currently available in the Delphi/C++Builder implementation only. The .NET implementation reads only the first inbound stream per connection and exposes no multi-stream surface.

Example


oServer := TsgcQUICServer.Create(nil);
oServer.Port := 4433;
oServer.QUICOptions.SSLOptions.CertFile := 'server.crt';
oServer.QUICOptions.SSLOptions.KeyFile := 'server.key';
oServer.AlwaysMultiStream := True; // required, or the event never fires
oServer.OnQUICStreamData := OnQUICStreamDataEvent;
oServer.Start;

procedure TfrmServer.OnQUICStreamDataEvent(Sender: TObject;
  const aConnection: TsgcQUICServerConnection; aStreamId: Int64;
  aUnidirectional: Boolean; const aData: TBytes);
var
  oStream: TsgcQUICServerStream;
begin
  Log(Format('%d bytes on stream %d (uni=%s)',
    [Length(aData), aStreamId, BoolToStr(aUnidirectional, True)]));

  if aUnidirectional then
    Exit; // the peer owns the write side of its one-way stream

  // echo back on the same stream
  oStream := aConnection.FindStreamById(aStreamId);
  if Assigned(oStream) then
    oServer.WriteStreamData(oStream, aData);
end;

Back to Events