This document defines a set of ECMAScript APIs in WebIDL to allow data to be sent and received between a browser and server implementing the QUIC protocol. This specification is being developed in conjunction with a protocol specification developed by the IETF QUIC Working Group.
This specification uses QUIC [[!QUIC-TRANSPORT]] to send data to and receive data from servers. It can be used like WebSockets but with support for multiple streams, unidirectional streams, out-or-order deliver, and unreliable delivery.
The QUIC API presented in this specification represents a preliminary proposal based on work-in-progress within the IETF QUIC WG. Since the QUIC transport specification is a work-in-progress, both the protocol and API are likely to change significantly going forward.
This specification defines conformance criteria that apply to a single product: the user agent that implements the interfaces that it contains.
Conformance requirements phrased as algorithms or specific steps may be implemented in any manner, so long as the end result is equivalent. (In particular, the algorithms defined in this specification are intended to be easy to follow, and not intended to be performant.)
Implementations that use ECMAScript to implement the APIs defined in this specification MUST implement them in a manner consistent with the ECMAScript Bindings defined in the Web IDL specification [[!WEBIDL-1]], as this specification uses that specification and terminology.
The EventHandler
interface, representing a callback used for event handlers, and the ErrorEvent
interface are defined in [[!HTML51]].
The concepts queue a task, fires a simple event and networking task source are defined in [[!HTML51]].
The term finished reading means that the application has read all
available data up to the STREAM frame with the FIN bit set, which causes
the [[\Readable]] slot to be set to false.
The terms event, event handlers and event handler event types are defined in [[!HTML51]].
When referring to exceptions, the terms throw and create are defined in [[!WEBIDL-1]].
The terms fulfilled, rejected, resolved, pending and settled used in the context of Promises are defined in [[!ECMASCRIPT-6.0]].
The QuicTransportBase is the base interface
for QuicTransport. Most of the functionality of a
QuicTransport is in the base class to allow for other
subclasses (such as a p2p variant) to share the same interface.
An QuicTransportBase instance can be associated to
one or more QuicBidirectionalStream,
QuicSendStream, or QuicReceiveStream
instances.
interface QuicTransportBase {
readonly attribute QuicTransportState state;
readonly attribute unsigned short maxDatagramSize;
void stop (QuicTransportStopInfo stopInfo);
Promise<QuicBidirectionalStream> createBidirectionalStream ();
Promise<QuicSendStream> createSendStream (optional QuicStreamParameters parameters);
Promise<void> readyToSendDatagram ();
Promise<boolean> sendDatagram (Uint8Array data);
Promise<sequence<Uint8Array>> receiveDatagrams ();
attribute EventHandler onstatechange;
attribute EventHandler onerror;
attribute EventHandler onreceivestream;
attribute EventHandler onbidirectionalstream;
};
state of type QuicTransportState, readonlyThe current state of the QUIC transport. On getting, it MUST return the value of the [[\QuicTransportState]] internal slot.
maxDatagramSize of type unsigned short, readonlyThe maximum size data that may be passed to sendDatagram.
onstatechange of type EventHandlerThis event handler, of event handler event type
statechange, MUST
be fired any time the [[\QuicTransportState]] slot changes, unless
the state changes due to calling stop.
onerror of type EventHandlerThis event handler, of event handler event type error,
MUST be fired on reception of a QUIC
error; an implementation SHOULD include QUIC error information in
error.message (defined in [[!HTML51]] Section 7.1.3.8.2). This
event MUST be fired before the
onstatechange event.
onreceivestream of type EventHandlerThis event handler, of event handler event type
receivestream,
MUST be fired on when data is received
from a newly created remote QuicReceiveStream for the
first time.
onbidirectionalstream of type EventHandlerThis event handler, of event handler event type
bidirectionalstream,
MUST be fired when data is received
from a newly created remote QuicBidirectionalStream for the
first time.
stopStops and closes the QuicTransportBase object.
This triggers an Immediate Close as described in [[QUIC-TRANSPORT]] section 10.3.
When stop is called, the user agent MUST
run the following steps:
QuicTransportBase
on which stop is invoked."closed"
then abort these steps."closed".stopInfo be the first argument.void
| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| stopInfo | QuicTransportStopInfo |
✘ | ✘ |
createBidirectionalStreamCreates an QuicBidirectionalStream object.
When createBidectionalStream is called, the user agent
MUST run the following
steps:
Let transport be the QuicTransportBase
on which createBidectionalStream is invoked.
If transport's state is "closed" or
"failed", immediately return a new rejected promise with a
newly created InvalidStateError and abort these steps.
If transport's state is "connected",
immediately return a new resolved promise with a newly created
QuicBidirectionalStream object,
add the QuicBidirectionalStream to the transport
and abort these steps.
Let p be a new promise.
Return p and continue the following steps in the background.
Resolve p with a newly created
QuicBidirectionalStream object,
add the QuicBidirectionalStream to the transport
when all of the following conditions are met:
transport's state has transitioned to
"connected"Reject p with a newly created
InvalidStateError when all of the following conditions are met:
transport's state transitions to
"closed" or "failed"Promise<QuicBidirectionalStream>
createSendStreamCreates an QuicSendStream object.
When createSendStream is called, the user agent
MUST run the following
steps:
Let transport be the QuicTransportBase
on which createSendStream is invoked.
If transport's state is "closed" or
"failed", immediately return a new rejected promise with a
newly created InvalidStateError and abort these steps.
If transport's state is "connected",
immediately return a new resolved promise with a newly created
QuicSendStream object,
add the QuicSendStream to the transport
and abort these steps.
Let p be a new promise.
Return p and continue the following steps in the background.
Resolve p with a newly created
QuicSendStream object,
add the QuicSendStream to the transport
when all of the following conditions are met:
transport's state has transitioned to
"connected"Reject p with a newly created
InvalidStateError when all of the following conditions are met:
transport's state transitions to
"closed" or "failed"Promise<QuicSendStream>
readyToSendDatagramReturns a promise that will be resolved when the QuicTransport can send a datagram as defined by [[QUIC-DATAGRAM]].
When readyToSendDatagram is called, the user agent
MUST run the following
steps:
Let p be a new promise.
Let transport be the
QuicTransportBase on which
readyToSendDatagram is invoked.
Return p and continue the following steps in the background.
If transport can send a datagram, imediately resolve p and abort these steps.
If transport's state is "failed"
or "closed" immediately reject p with a newly
created InvalidStateError and abort these steps.
If transport is blocked from sending a datagram due to
congestion control, resolve p when transport
is no longer blocked.
reject p with a newly created
InvalidStateError if the transport's
state transitions to "failed" or "closed".
Promise<void>
sendDatagramSends a datagram as defined by [[QUIC-DATAGRAM]].
When sendDatagram is called, the user agent
MUST run the following
steps:
Let transport be
the QuicTransportBase on
which sendDatagram is invoked.
If transport's state is not connected return
a promise rejected with a newly created
InvalidStateError and abort these steps.
If data is too large to fit into a
datagram, return a promise rejected with a newly created
InvalidArgumentError and abort these steps.
If transport is unable to send the datagram due
to congestion control, return a promise rejected with
a newly created InvalidStateError and abort
these steps.
Let p be a new promise.
Return p and continue the following steps in the background.
| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| data | Uint8Array |
✘ | ✘ |
Promise<boolean>
receiveDatagramsIf datagrams have been received since the last call to receiveDatagrams(), return a new promise resolved with all of the received datagrams.
If not, return a new promise that will resolve when more datagrams are received, resolved with all datagrams received.
If too many datagrams are queued between calls to receiveDatagrams(), the implementation may drop datagrams and replace them with a null value in the sequence of datagrams returned in the next call to receiveDatagrams(). One null value may represent many dropped datagrams.
receiveDatagrams() may only be called once at a time. If a promised returned from a previous call is still unresolved, the user agent MUST return a new promise rejected with an InvalidStateError.
Promise<sequence<Uint8Array>>
To add the QuicBidirectionalStream to the QuicTransportBase
run the following steps:
Let stream be the newly created
QuicBidirectionalStream object.
Add stream to transport's [[\QuicTransportReadableStreams]] internal slot.
Add stream to transport's [[\QuicTransportWritableStreams]] internal slot.
Continue the following steps in the background.
Create stream's associated underlying data transport.
To add the QuicSendStream to the QuicTransportBase
run the following steps:
Let stream be the newly created
QuicSendStream object.
Add stream to transport's [[\QuicTransportWritableStreams]] internal slot.
Continue the following steps in the background.
Create stream's associated underlying data transport.
The QuicStreamParameters dictionary includes information
relating to QUIC stream configuration.
dictionary QuicStreamParameters {
bool disableRetransmissions = false;
};
disableRetransmissions of type bool, defaulting to
falsedisableRetransmissions, with a default of false. If
true, the stream will be sent without retransmissions. If false, the
stream will be sent with retransmissions.
The receivestream event uses the
ReceiveStreamEvent interface.
[ Constructor (DOMString type, ReceiveStreamEventInit eventInitDict), Exposed=Window]
interface ReceiveStreamEvent : Event {
readonly attribute QuicReceiveStream stream;
};
ReceiveStreamEvent| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| type | DOMString |
✘ | ✘ | |
| eventInitDict | ReceiveStreamEventInit |
✘ | ✘ |
stream of type QuicReceiveStream, readonlyThe stream
attribute represents the QuicReceiveStream object
associated with the event.
The ReceiveStreamEventInit dictionary includes
information on the configuration of the QUIC stream.
dictionary ReceiveStreamEventInit : EventInit {
QuicReceiveStream stream;
};
stream of type QuicReceiveStreamThe QuicReceiveStream object associated with the
event.
The bidirectionalstream event uses the
BidirectionalStreamEvent interface.
[ Constructor (DOMString type, BidirectionalStreamEventInit eventInitDict), Exposed=Window]
interface BidirectionalStreamEvent : Event {
readonly attribute QuicBidirectionalStream stream;
};
BidirectionalStreamEvent| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| type | DOMString |
✘ | ✘ | |
| eventInitDict | BidirectionalStreamEventInit |
✘ | ✘ |
stream of type QuicBidirectionalStream, readonlyThe stream
attribute represents the QuicBidirectionalStream object
associated with the event.
The BidirectionalStreamEventInit dictionary includes
information on the configuration of the QUIC stream.
dictionary BidirectionalStreamEventInit : EventInit {
QuicBidirectionalStream stream;
};
stream of type QuicBidirectionalStreamThe QuicBidirectionalStream object associated with the
event.
QuicTransportState indicates the state of the QUIC
transport.
enum QuicTransportState {
"new",
"connecting",
"connected",
"closed",
"failed"
};
| Enumeration description | |
|---|---|
new |
The |
connecting |
QUIC is in the process of negotiating a secure connection.
Once a secure connection is negotiated
(but prior to verification of the remote fingerprint, enabled by calling
|
connected |
QUIC has completed negotiation of a secure connection. Outgoing data and media can now flow through. |
closed |
The QUIC connection has been closed intentionally via a call to
|
failed |
The QUIC connection has been closed as the result of an error (such as
receipt of an error alert or a failure to validate the remote
fingerprint). When the
|
The QuicTransportStopInfo dictionary includes information
relating to the error code for stopping a QuicTransportBase.
This information is used to set the error code and reason for an CONNECTION_CLOSE
frame.
dictionary QuicTransportStopInfo {
unsigned short errorCode = 0;
DOMString reason = "";
};
errorCode of type unsigned short, defaulting to
0.The error code used in CONNECTION_CLOSE frame.
reason of type DOMString, defaulting to ""The reason for stopping the QuicTransportBase
The QuicTransportBase is a subclass of
QuicTransportBase focused on client/server use cases.
[ Constructor (DOMString host, unsigned short port), Exposed=Window]
interface QuicTransport : QuicTransportBase {
};
QuicTransport constructor is invoked,
the user agent MUST run the
following steps:
NotSupportedError and abort these steps.
QuicTransport object.
QuicWritableStream
objects, initialized to empty.
QuicReadableStream
objects, initialized to empty.
"connecting".
Uint8Array, initialized to empty.
Promise<sequence<Uint8Array>>?,
initialized to null.
"failed" and abort these steps.
"failed" and abort these steps.
",".
"*",
set quictransport's [[\QuicTransportState]]
internal slot to "connected" and abort these steps.
"failed".
QuicTransport| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| host | DOMString |
✘ | ✘ | The host to connect to. |
| port | unsigned short |
✘ | ✘ | The port to connect to. |
The QUIC Stream API includes information relating
to a QUIC stream.
QuicBidirectionalStream, QuicSendStream,
and QuicReceiveStream instances are associated to
a QuicTransportBase instance.
An QuicBidirectionalStream can be created in the following ways:
QuicTransportBase's createBidirectionalStream method.bidirectionalstream event on the
QuicTransportBase.An QuicSendStream can be created in the following ways:
QuicTransportBase's createSendStream method.An QuicReceiveStream can be created in the following
ways:
receivestream event on the
QuicTransportBase.
[ Exposed=Window ]
interface mixin QuicWritableStream {
readonly attribute boolean writable;
readonly attribute unsigned long writeBufferedAmount;
readonly attribute Promise<QuicStreamAbortInfo> writingAborted;
void write (QuicStreamWriteParameters data);
void abortWriting (QuicStreamAbortInfo abortInfo);
Promise<void> waitForWriteBufferedAmountBelow(unsigned long threshold);
};
The QuicWritableStream will initialize with
the following:
QuicWritableStream.true.writable of type boolean
readonlyThe writable
attribute represents whether data can be written to the
QuicWritableStream. On getting it
MUST return the value of the
[[\Writable]] slot.
writeBufferedAmount of type unsigned
long, readonlyThe writeBufferedAmount
attribute represents the number of bytes of application data
that have been queued using write but that, as of the last
time the event loop started executing a task, had not yet been transmitted
to the network. This includes any data sent during the execution of the
current task, regardless of whether the user agent is able to
transmit text asynchronously with script execution. This does not
include framing overhead incurred by the protocol, or buffering done
by the operating system or network hardware. On getting, it
MUST return the value of the
QuicWritableStream's [[\WriteBufferedAmount]] internal slot.
writingAborted of type QuicStreamAbortInfo
readonlyThe writingAborted
attribute represents a promise that resolves when the
STOP_SENDING frame is received from the QuicReadableStream.
When the stream receives a STOP_SENDING frame from its corresponding
QuicReadableStream, the user agent
MUST run the following:
QuicWritableStream object.
false.QuicTransportBase,
which the stream was created from.
QuicStreamAbortInfo with the errorCode
set to the value from the STOP_SENDING frame.writeWrites data to the stream. When the remote QuicTransportBase
receives the STREAM frame from this stream for the first time, it will trigger the
creation of the corresponding remote stream. When the write method is
called, the user agent MUST
run the following steps:
QuicWritableStream
object on which data is to be sent.false, throw a NotSupportedError and abort
these steps.false,
throw an InvalidStateError and abort these steps.true, run the
following:false.QuicTransportBase,
which the stream was created from.QuicTransportBase's onerror
EventHandler.| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| data | QuicStreamWriteParameters |
✘ | ✘ |
void
abortWritingA hard shutdown of the QuicWritableStream. It may be called
regardless of whether the QuicWritableStream
was created by the local or remote peer. When the abortWriting()
method is called, the user agent MUST
run the following steps:
QuicWritableStream object
which is about to abort writing.false,
throw an InvalidStateError and abort these steps.false.QuicTransportBase,
which the stream was created from.| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| abortInfo | QuicStreamAbortInfo |
✘ | ✘ |
void
waitForWriteBufferedAmountBelowwaitForWriteBufferedAmountBelow resolves the promise when
the data queued in the write buffer falls below the given threshold.
If waitForWriteBufferedAmountBelow
is called multiple times, multiple promises could be resolved when the
write buffer falls below the threshold for each promise. The Promise will
be rejected with a newly created InvalidStateError if the
stream's [[\Writable]] slot transitions from true to false
and the promise isn't settled. When the waitForWriteBufferedAmountBelow method
is called, the user agent MUST run
the following steps:
QuicWritableStream
object on which waitForWriteBufferedAmountBelow was invoked.false, reject p with a
newly created InvalidStateError and abort
these steps.undefined.| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| threshold | unsigned long |
✘ | ✘ |
Promise<void>
[ Exposed=Window ]
interface mixin QuicReadableStream {
readonly attribute boolean readable;
readonly attribute unsigned long readableAmount;
readonly attribute Promise<QuicStreamAbortInfo> readingAborted;
QuicStreamReadResult readInto (Uint8Array data);
void abortReading (QuicStreamAbortInfo abortInfo);
Promise<void> waitForReadable(unsigned long amount);
};
The QuicReadableStream will initialize with
the following:
QuicReadableStream.true.readable of type boolean,
readonlyThe readable
attribute represents whether data can be read from the QuicReadableStream.
On getting, it MUST return the value of the
QuicReadableStream's [[\Readable]] slot.
readableAmount of type unsigned
long, readonlyThe readableAmount
attribute represents the number of bytes buffered for access by
readInto but that, as of the last time the event loop
started executing a task, had not yet been read. This does not include
framing overhead incurred by the protocol, or buffers associated with
the network hardware. On getting, it MUST
return the value of the QuicReadableStream's
[[\ReadableAmount]] internal slot.
readingAborted of type QuicStreamAbortInfo
readonlyThe readingAborted
attribute represents a promise that resolves when the
RST_STREAM frame is received from the QuicWritableStream.
When the stream receives a RST_STREAM frame from its corresponding
QuicWritableStream, the user agent
MUST run the following:
QuicReadableStream
objectfalse.QuicTransportBase,
which the stream was created from.
QuicStreamAbortInfo with errorCode
set to the value of the errror code from the RST_STREAM frame.readIntoReads from the QuicReadableStream into the buffer specified
by the first argument and returns QuicStreamReadResult.
When the readInto method is called, the user agent
MUST run the following steps:
QuicReadableStream object
on which readInto is invoked.false,
throw an InvalidStateError, then abort these steps.QuicStreamReadResult
to be returned.amount set to 0 and finished set to
true and abort these steps.amount to the size of
data in bytes.finished to true.false.QuicTransportBase,
which the stream was created from.
finished to false.| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| data | Uint8Array |
✘ | ✘ |
QuicStreamReadResult
abortReadingA hard shutdown of the QuicReadableStream. It may be called
regardless of whether the QuicReadableStream object
was created by the local or remote peer. When the abortReading()
method is called, the user agent MUST
run the following steps:
QuicReadableStream object
which is about to abort reading.false,
throw an InvalidStateError and abort these steps.false.QuicTransportBase,
which the stream was created from.
| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| abortInfo | QuicStreamAbortInfo |
✘ | ✘ |
void
waitForReadablewaitForReadable waits for data to become available, or
for the QuicReadableStream to be finished reading. It
resolves the promise when the data queued in the read buffer
increases above the amount provided as an argument or when a STREAM frame
with the FIN bit set has been received. If waitForReadable
is called multiple times, multiple promises could be resolved.
The Promise will be rejected with a newly created
InvalidStateError if the stream's
[[\Readable]] slot transitions from true to false and the promise
isn't settled. When the waitForReadable method is
called, the user agent MUST
run the following steps:
QuicReadableStream
on which waitForReadable is invoked.false, reject p with a
newly created InvalidStateError and abort
these steps.undefined when
any of the following conditions are met:
| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| amount | unsigned long |
✘ | ✘ |
Promise<void>
[ Exposed=Window ]
interface QuicStream {
readonly attribute unsigned long long streamId;
readonly attribute QuicTransportBase transport;
};
streamId of type unsigned long long, readonlyThe readonly attribute referring to the ID of the
QuicStream object.
transport of type QuicTransportBase, readonlyThe readonly attribute referring to the related QuicTransportBase object.
[ Exposed=Window ]
interface QuicBidirectionalStream : QuicStream {
};
QuicBidirectionalStream includes QuicWritableStream;
QuicBidirectionalStream includes QuicReadableStream;
[ Exposed=Window ]
interface QuicSendStream : QuicStream {
};
QuicSendStream includes QuicWritableStream;
[ Exposed=Window ]
interface QuicReceiveStream : QuicStream {
};
QuicReceiveStream includes QuicReadableStream;
The QuicStreamWriteParameters dictionary includes information
relating to the data to be written with QuicWritableStream.write.
dictionary QuicStreamWriteParameters {
Uint8Array data;
boolean finished = false;
};
data of type Uint8Array.The data to be written.
finished of type boolean.Set to true if this is the last data to be written.
This will result in a STREAM frame with the FIN bit set.
The QuicStreamReadResult dictionary includes information
relating to the result returned from readInto.
dictionary QuicStreamReadResult {
unsigned long amount;
boolean finished = false;
};
amount of type unsigned long.The amount of data read in bytes.
finished of type boolean.Set to true if the QuicReadableStream has
finished reading.
The QuicStreamAbortInfo dictionary includes information
relating to the error code for aborting a QUIC stream. This could be used either
in a RST_STREAM frame or STOP_SENDING frame.
dictionary QuicStreamAbortInfo {
unsigned short errorCode = 0;
};
errorCode of type unsigned short.The error code used in the RST_STREAM or STOP_SENDING frame. The default value of 0 means "STOPPING."
This section is non-normative; it specifies no new behaviour, but instead summarizes information already present in other parts of the specification.
The fact that communication is taking place cannot be hidden from adversaries that can observe the network, so this has to be regarded as public information.
Since the QUIC protocol utilizes a cryptographic negotiation based on TLS 1.3 [[TLS13]] in order to encrypt communications, it provides confidentiality.
The following events fire on QuicTransportBase objects:
| Event name | Interface | Fired when... |
|---|---|---|
error |
ErrorEvent |
The QuicTransportBase object has encountered an error. |
statechange |
Event |
The QuicTransportState changed. |
receivestream |
ReceiveStreamEvent |
A new QuicReceiveStream is dispatched to the
script in response to the remote peer creating a send only QUIC stream and
sending data on it. Prior to receivestream
firing, the QuicReceiveStream is added to
QuicTransportBase's [[\QuicTransportReadableStreams]]
internal slot. |
bidirectionalstream |
BidirectionalStreamEvent |
A new QuicBidirectionalStream is dispatched to the
script in response to the remote peer creating a bidirectional QUIC stream and
sending data on it. Prior to bidirectionalstream
firing, the QuicBidirectionalStream is added to the
QuicTransportBase's [[\QuicTransportReadableStreams]]
and [[\QuicTransportWritableStreams]] internal slots. |
Unreliable delivery can be achieved by creating many streams with retransmissions disabled, each transporting a single small message.
let quic = getQuicTransport();
let messages = getMessages();
for (msg in messages) {
quic.createSendStream({disableRetransmissions: true}).write({data: msg, finished: true});
}
Sending a buffer of QUIC datagrams can be achieved by using the
sendDatagram and readyToSendDatagram methods. In
the following example datagrams are only sent if the
QuicTransport is ready to send, however the sending is not
blocked on the ACK promise returned from sendDatagram (these are
ignored in this example).
const quic = getQuicTransport();
const datagrams = getDatagramsToSend();
datagrams.forEach((datagram) => {
await quic.readyToSendDatagram();
quic.sendDatagram(datagram);
});
Sending QUIC datagrams at a fixed rate regardless if the transport is ready to
send can be achieved by simply using sendDatagram and not using
the readyToSendDatagram method. More complex scenarios can utilize
the readyToSendDatagram method.
// Sends datagrams every 100 ms.
const quic = getQuicTransport();
setInterval(() => {
quic.sendDatagram(createDatagram());
}, 100);
Receiving QUIC datagrams can be achieved by using the
receiveDatagrams method, remembering to check for null values
indicating that packets are not being processed quickly enough.
const quic = getQuicTransport();
const datagrams = await quic.receiveDatagrams();
for (let data of datagrams) {
if (data == null) {
// Log that datagrams were lost. Look into making the event handler faster
// or reducing the send rate of the remote side.
} else {
// Process the data
}
};
This section will be removed before publication.
The editors wish to thank the Working Group chairs and Team Contact, Harald Alvestrand, Stefan Håkansson, Bernard Aboba and Dominique Hazaël-Massieux, for their support. Contributions to this specification were provided by Robin Raymond.
The QuicTransport and QuicStream objects
were initially described in the W3C ORTC CG,
and have been adapted for use in this specification.