js/net/quic/stream
js/net/quic/stream.ts
fino:net/quic/stream — bidirectional and unidirectional QUIC streams.
A QuicStream exposes QUIC stream data through Web Streams and lower-level
Fino byte reader and writer objects. Streams are created by
QuicConnection.openStream() or accepted with
QuicConnection.acceptStream().
import type { QuicConnection } from 'fino:net/quic/connection';
import type { QuicStream } from 'fino:net/quic/stream';
export async function send(connection: QuicConnection, data: Uint8Array) {
const stream: QuicStream = await connection.openStream();
await stream.writer.write(data);
await stream.close();
}
Classes
class QuicStream extends EventTarget {
One QUIC stream multiplexed inside a QuicConnection.
Obtained from connection.openBidirectionalStream() /
openUnidirectionalStream() or accepted with connection.acceptStream() /
the 'stream' event; never constructed directly. A bidirectional stream has
both a readable and a writable half; a unidirectional stream has only one,
depending on which side opened it. Read and write through the byte-oriented
reader/writer, or through the readable/writable Web Streams adapters.
It extends EventTarget and emits 'reset', 'stopsending', and
'blocked'.
reset() abruptly terminates the sending side with an application error
code; stopSending() asks the peer to stop sending on the receiving side.
resetAt() resets after reliably delivering a prefix, when the ngtcp2 build
supports it.
const stream = await conn.openBidirectionalStream();
await stream.writer.write(new TextEncoder().encode('ping'));
await stream.writer.close();
for await (const chunk of stream.readable) console.log(chunk.length);
Readonly Properties
readonly id: number
Numeric QUIC stream identifier, encoding initiator and directionality.
readonly direction: 'bidirectional' | 'unidirectional'
Whether the stream is bidirectional or send/receive-only.
readonly reader: BytesReader
Byte-oriented reader for the receiving half (closed on send-only streams).
readonly writer: QuicBytesWriter
Byte-oriented writer for the sending half (throws on receive-only streams).
Constructors
constructor(
id: number,
direction: 'bidirectional' | 'unidirectional',
connection: QuicConnection,
incoming = false
)
Getters
get readable(): ReadableStream<Uint8Array>
Web ReadableStream view of the receiving half.
Lazily created and cached. Cancelling the stream issues stopSending(0).
Prefer reader for lower-level byte access.
get writable(): WritableStream<Uint8Array>
Web WritableStream view of the sending half.
Lazily created and cached. Closing it sends FIN; aborting it resets the
stream (with the abort reason as the error code when it is a number). Prefer
writer for lower-level byte access.
get stats(): QuicStreamStats
Frozen snapshot of this stream's byte and offset counters.
Methods
reset(errorCode: number): void
Abruptly terminate the sending half with an application error code.
Sends RESET_STREAM to the peer; any unacknowledged outgoing data is discarded. Throws if the owning connection is already closed.
stream.reset(0x101); // abort with an application-defined code
resetAt(errorCode: number, finalSize: number | bigint): void
Reset the stream after reliably delivering bytes up to finalSize.
This requires ngtcp2 support for the QUIC reliable reset extension. Builds without that native symbol throw a clear unsupported error.
stopSending(errorCode: number): void
Ask the peer to stop sending on the receiving half.
Sends STOP_SENDING with the given application error code and closes the local receive side. No-op on a locally opened unidirectional stream (which has no receiving half). Throws if the owning connection is already closed.
stream.stopSending(0); // we no longer want incoming data
Types
type QuicStreamStats = {
readonly createdAt: number;
readonly openedAt: number | null;
readonly receivedAt: number | null;
readonly ackedAt: number | null;
readonly destroyedAt: number | null;
readonly bytesReceived: number;
readonly bytesSent: number;
readonly bytesAcked: number;
readonly finalSize: number | null;
readonly maxOffset: number;
readonly maxOffsetAcked: number;
readonly maxOffsetReceived: number;
readonly maxOffsetSent: number;
readonly bytesAccumulated: number;
readonly maxBytesAccumulated: number;
}
Per-stream byte and offset counters, read from QuicStream.stats.
Each read returns a frozen snapshot. finalSize is null until the stream's
final size is known (a FIN was received or the stream was reset). The
maxOffset* fields track how far each end of the stream has progressed, and
bytesAccumulated/maxBytesAccumulated report current and peak buffered
receive bytes so a slow reader's backlog is visible.