This document defines a set of ECMAScript APIs in WebIDL to allow data to be sent and received between a browser and server, implementing pluggable protocols underneath with common APIs on top. APIs specific to QUIC are also provided. This specification is being developed in conjunction with a protocol specification developed by the IETF QUIC Working Group.
This specification uses pluggable protocols, with QUIC [[!QUIC-TRANSPORT]] as one such protocol, to send data to and receive data from servers. It can be used like WebSockets but with support for multiple streams, unidirectional streams, out-of-order delivery, and reliable as well as unreliable transport.
The 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]].
A UnidirectionalStreamsTransport
can send and receive unidirectional streams.
Data within a stream is delivered in order, but data between streams may be delivered out of order.
Data is generally sent reliably, but retransmissions may be disabled
or the stream may aborted to produce a form of unreliability.
All stream data is encrypted and congestion-controlled.
interface mixin UnidirectionalStreamsTransport { Promise<SendStream> createSendStream (optional SendStreamParameters parameters); attribute EventHandler onreceivestream; };
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 ReceiveStream
for the
first time.
createSendStream
Creates an SendStream
object.
When createSendStream
is called, the user agent
MUST run the following
steps:
Let transport be the UnidirectionalStreamsTransport
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
SendStream
object,
add the SendStream 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
SendStream
object and
add the SendStream to the transport
when all of the following conditions are met:
The transport's state
has transitioned to
"connected"
Stream creation flow control is not being violated by exceeding the max stream limit set by the remote endpoint, as specified in [[QUIC-TRANSPORT]].
p has not been settled
Reject p with a newly created
InvalidStateError
when all of the following conditions are met:
The transport's state
transitions to
"closed"
or "failed"
p has not been settled
Promise<SendStream>
To add the SendStream to the UnidirectionalStreamsTransport
run the following steps:
Let stream be the newly created
SendStream
object.
Add stream to transport's [[\OutgoingStreams]] internal slot.
Continue the following steps in the background.
Create stream's associated underlying transport.
The QuicStreamParameters
dictionary includes information
relating to stream configuration.
dictionary SendStreamParameters { bool disableRetransmissions = false; };
disableRetransmissions
of type bool, defaulting to
false
disableRetransmissions, with a default of false
. If
true, the stream will be sent without retransmissions. If false, the
stream will be sent with retransmissions.
If the WebTransport is unable to send without retransmissions, it may ignore this value.
The receivestream
event uses the
ReceiveStreamEvent
interface.
[ Constructor (DOMString type, ReceiveStreamEventInit eventInitDict), Exposed=Window] interface ReceiveStreamEvent : Event { readonly attribute ReceiveStream stream; };
ReceiveStreamEvent
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
type | DOMString |
✘ | ✘ | |
eventInitDict | ReceiveStreamEventInit |
✘ | ✘ |
stream
of type ReceiveStream, readonlyThe stream
attribute represents the ReceiveStream
object
associated with the event.
The ReceiveStreamEventInit
dictionary includes
information on the configuration of the stream.
dictionary ReceiveStreamEventInit : EventInit { ReceiveStream stream; };
stream
of type ReceiveStreamThe ReceiveStream
object associated with the
event.
A BidirectionalStreamsTransport
can send and receive bidirectional streams.
Data within a stream is delivered in order, but data between streams may be delivered out of order.
Data is generally sent reliably, but retransmissions may be disabled
or the stream may aborted to produce a form of unreliability.
All stream data is encrypted and congestion-controlled.
interface BidirectionalStreamsTransport { Promise<BidirectionalStream> createBidirectionalStream (); attribute EventHandler onbidirectionalstream; };
onbidirectionalstream
of type EventHandlerThis event handler, of event handler event type
bidirectionalstream
,
MUST be fired when data is received
from a newly created remote BidirectionalStream
for the
first time.
createBidirectionalStream
Creates an BidirectionalStream
object.
When createBidectionalStream
is called, the user agent
MUST run the following
steps:
Let transport be the BidirectionalStreamsTransport
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
BidirectionalStream
object,
add the BidirectionalStream 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
BidirectionalStream
object and
add the BidirectionalStream to the transport
when all of the following conditions are met:
The transport's state
has transitioned to
"connected"
Stream creation flow control is not being violated by exceeding the max stream limit set by the remote endpoint, as specified in [[QUIC-TRANSPORT]].
p has not been settled
Reject p with a newly created
InvalidStateError
when all of the following conditions are met:
The transport's state
transitions to
"closed"
or "failed"
p has not been settled
Promise<BidirectionalStream>
To add the BidirectionalStream to the BidirectionalStreamsTransport
run the following steps:
Let stream be the newly created
BidirectionalStream
object.
Add stream to transport's [[\IncomingStreams]] internal slot.
Add stream to transport's [[\OutgoingStreams]] internal slot.
Continue the following steps in the background.
Create stream's associated underlying transport.
The bidirectionalstream
event uses the
BidirectionalStreamEvent
interface.
[ Constructor (DOMString type, BidirectionalStreamEventInit eventInitDict), Exposed=Window] interface BidirectionalStreamEvent : Event { readonly attribute BidirectionalStream stream; };
BidirectionalStreamEvent
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
type | DOMString |
✘ | ✘ | |
eventInitDict | BidirectionalStreamEventInit |
✘ | ✘ |
stream
of type BidirectionalStream, readonlyThe stream
attribute represents the BidirectionalStream
object
associated with the event.
The BidirectionalStreamEventInit
dictionary includes
information on the configuration of the stream.
dictionary BidirectionalStreamEventInit : EventInit { BidirectionalStream stream; };
stream
of type BidirectionalStreamThe BidirectionalStream
object associated with the
event.
A DatagramTransport
can send and receive datagrams.
Datagrams are sent out of order, unreliably, and have a limited maximum size.
Datagrams are encrypted and congestion controlled.
interface mixin DatagramTransport { readonly attribute unsigned short maxDatagramSize; Promise<void> readyToSendDatagram (); Promise<boolean> sendDatagram (Uint8Array data); Promise<sequence<Uint8Array>> receiveDatagrams (); };
maxDatagramSize
of type unsigned short, readonlyThe maximum size data that may be passed to sendDatagram.
readyToSendDatagram
Returns a promise that will be resolved when the DatagramTransport can send a datagram.
When readyToSendDatagram
is called, the user agent
MUST run the following
steps:
Let p be a new promise.
Let transport be the
DatagramTransport
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>
sendDatagram
Sends a datagram.
When sendDatagram
is called, the user agent
MUST run the following
steps:
Let transport be
the DatagramTransport
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>
receiveDatagrams
If 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>>
The WebTransport
includes the methods common to all transports,
such as state, state changes, and the ability to close the transport.
interface mixin WebTransport { readonly attribute WebTransportState state; void close (WebTransportCloseInfo closeInfo); attribute EventHandler onstatechange; attribute EventHandler onerror; };
state
of type WebTransportState, readonlyThe current state of the transport. On getting, it MUST return the value of the [[\WebTransportState]] internal slot.
onstatechange
of type EventHandlerThis event handler, of event handler event type
statechange
, MUST
be fired any time the [[\WebTransportState]] slot changes, unless
the state changes due to calling close
.
onerror
of type EventHandlerThis event handler, of event handler event type error
,
MUST be fired on reception of an
error; an implementation SHOULD include error information in
error.message (defined in [[!HTML51]] Section 7.1.3.8.2). This
event MUST be fired before the
onstatechange
event.
close
Closes the WebTransport
object.
For QUIC, this triggers an Immediate Close as described in [[QUIC-TRANSPORT]] section 10.3.
When close
is called, the user agent MUST
run the following steps:
WebTransport
on which close
is invoked."closed"
then abort these steps."closed"
.closeInfo
be the first argument.void
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
closeInfo | WebTransportCloseInfo |
✘ | ✘ |
WebTransportState
indicates the state of the
transport.
enum WebTransportState { "new", "connecting", "connected", "closed", "failed" };
Enumeration description | |
---|---|
new |
The |
connecting |
The transport is in the process of negotiating a secure connection. Once a secure connection is negotiated, incoming data can flow through. |
connected |
The transport has completed negotiation of a secure connection. Outgoing data and media can now flow through. |
closed |
The transport has been closed intentionally via a call to
|
failed |
The transport has been closed as the result of an error (such as
receipt of an error alert). When the
|
The WebTransportCloseInfo
dictionary includes information
relating to the error code for closing a WebTransport
.
For QUIC, this information is used to set the error code and reason for an CONNECTION_CLOSE
frame.
dictionary WebTransportCloseInfo { unsigned short errorCode = 0; DOMString reason = ""; };
errorCode
of type unsigned short, defaulting to
0
.The error code.
reason
of type DOMString, defaulting to ""
The reason for closing the WebTransport
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.
A QuicTransportBase
is a
UnidirectionalStreamsTransport
, a
BidirectionalStreamsTransport
, and a
DatagramTransport
.
SendStreams and ReceiveStreams are implemented with unidirectional QUIC streams as defined in [[!QUIC-TRANSPORT]].
BidirectionalStreams are implemented with bidirectional QUIC streams as defined in [[!QUIC-TRANSPORT]].
Datagrams are implemented with QUIC datagrams as defined in [[QUIC-DATAGRAM]].
interface QuicTransportBase { }; QuicTransportBase includes UnidirectionalStreamsTransport; QuicTransportBase includes BidirectionalStreamsTransport; QuicTransportBase includes DatagramTransport; QuicTransportBase includes WebTransport;
The QuicTransport
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.
OutgoingStream
objects, initialized to empty.
IncomingStream
objects, initialized to empty.
"connecting"
.
Uint8Array
, initialized to empty.
Promise<sequence<Uint8Array>>?
,
initialized to null.
"failed"
and abort these steps.
"connected"
.
QuicTransport
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
host | DOMString |
✘ | ✘ | The host to connect to. |
port | unsigned short |
✘ | ✘ | The port to connect to. |
An OutgoingStream is a stream that can be written to,
as either a SendStream
or a BidirectionalStream
[ Exposed=Window ] interface mixin OutgoingStream { readonly attribute boolean writable; readonly attribute unsigned long writeBufferedAmount; readonly attribute Promise<StreamAbortInfo> writingAborted; void write (StreamWriteParameters data); void abortWriting (StreamAbortInfo abortInfo); Promise<void> waitForWriteBufferedAmountBelow(unsigned long threshold); };
The OutgoingStream
will initialize with
the following:
OutgoingStream
.true
.writable
of type boolean
readonlyThe writable
attribute represents whether data can be written to the
OutgoingStream
. 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
OutgoingStream
's [[\WriteBufferedAmount]] internal slot.
writingAborted
of type StreamAbortInfo
readonlyThe writingAborted
attribute represents a promise that resolves when the
a message from the remote side aborting the stream is received.
For QUIC, that message is a STOP_SENDING frame.
When the stream receives this mesage, the user agent
MUST run the following:
OutgoingStream
object.
false
.WebTransport
,
which the stream was created from.
StreamAbortInfo
with the errorCode
set to the value from the aborting message from the remote side.write
Buffer the given data to be written to the network when possible.
When the remote WebTransport
receives data for this stream for the first time, it will trigger the
creation of the corresponding remote IncomingStream
.
When the write
method is
called, the user agent MUST
run the following steps:
OutgoingStream
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
.WebTransport
,
which the stream was created from.WebTransport
's onerror
EventHandler.Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
data | StreamWriteParameters |
✘ | ✘ |
void
abortWriting
A hard shutdown of the OutgoingStream
. It may be called
regardless of whether the OutgoingStream
was created by the local or remote peer. When the abortWriting()
method is called, the user agent MUST
run the following steps:
OutgoingStream
object
which is about to abort writing.false
,
throw an InvalidStateError
and abort these steps.false
.WebTransport
,
which the stream was created from.Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
abortInfo | StreamAbortInfo |
✘ | ✘ |
void
waitForWriteBufferedAmountBelow
waitForWriteBufferedAmountBelow
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:
OutgoingStream
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>
The StreamWriteParameters
dictionary includes information
relating to the data to be written with OutgoingStream.write
.
dictionary StreamWriteParameters { 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.
For QUIC, this will result in a STREAM frame with the FIN bit set.
The StreamAbortInfo
dictionary includes information
relating to the error code for aborting an incoming or outgoing stream.
(For QUIC, in either a RST_STREAM frame or a STOP_SENDING frame).
dictionary StreamAbortInfo { unsigned short errorCode = 0; };
errorCode
of type unsigned short.The error code. The default value of 0 means "CLOSING."
An IncomingStream is a stream that can be read from,
as either a ReceiveStream
or a BidirectionalStream
[ Exposed=Window ] interface mixin IncomingStream { readonly attribute boolean readable; readonly attribute unsigned long readableAmount; readonly attribute Promise<StreamAbortInfo> readingAborted; StreamReadResult readInto (Uint8Array data); void abortReading (StreamAbortInfo abortInfo); Promise<void> waitForReadable(unsigned long amount); };
The IncomingStream
will initialize with
the following:
IncomingStream
.true
.readable
of type boolean,
readonlyThe readable
attribute represents whether data can be read from the IncomingStream
.
On getting, it MUST return the value of the
IncomingStream
'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 IncomingStream
's
[[\ReadableAmount]] internal slot.
readingAborted
of type StreamAbortInfo
readonlyThe readingAborted
attribute represents a promise that resolves when the
a message is received inidicating the remote side aborted the stream.
For QUIC, this is a RST_STREAM frame.
When the stream receives this message, the user agent
MUST run the following:
IncomingStream
object for which the abort message was received.false
.WebTransport
,
which the stream was created from.
StreamAbortInfo
with errorCode
set to the value of the errror code from the abot message.readInto
Reads from the IncomingStream
into the buffer specified
by the first argument and returns StreamReadResult
.
When the readInto
method is called, the user agent
MUST run the following steps:
IncomingStream
object
on which readInto
is invoked.false
,
throw an InvalidStateError
, then abort these steps.StreamReadResult
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
.WebTransport
,
which the stream was created from.
finished
to false.Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
data | Uint8Array |
✘ | ✘ |
StreamReadResult
abortReading
A hard shutdown of the IncomingStream
. It may be called
regardless of whether the IncomingStream
object
was created by the local or remote peer. When the abortReading()
method is called, the user agent MUST
run the following steps:
IncomingStream
object
which is about to abort reading.false
,
throw an InvalidStateError
and abort these steps.false
.WebTransport
,
which the stream was created from.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
abortInfo | StreamAbortInfo |
✘ | ✘ |
void
waitForReadable
waitForReadable
waits for data to become available, or
for the IncomingStream
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
message is received with an end indication (for QUIC, a STREAM frame
with the FIN bit set). 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:
IncomingStream
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>
The StreamReadResult
dictionary includes information
relating to the result returned from readInto
.
dictionary StreamReadResult { 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 IncomingStream
has
finished reading.
A collection of common attributes and methods of all streams.
[ Exposed=Window ] interface WebTransportStream { readonly attribute unsigned long long streamId; readonly attribute WebTransport transport; };
streamId
of type unsigned long long, readonlyThe readonly attribute referring to the ID of the
TransportStream
object.
transport
of type WebTransport, readonlyThe readonly attribute referring to the related WebTransport
object.
[ Exposed=Window ] interface BidirectionalStream : WebTransportStream { }; BidirectionalStream includes OutgoingStream; BidirectionalStream includes IncomingStream;
[ Exposed=Window ] interface SendStream : WebTransportStream { }; SendStream includes OutgoingStream;
[ Exposed=Window ] interface ReceiveStream : WebTransportStream { }; ReceiveStream includes IncomingStream;
An Http3Transport
is a
UnidirectionalStreamsTransport
, a
BidirectionalStreamsTransport
, and a
DatagramTransport
.
SendStreams, ReceiveStreams, and BidirectionalStreams are implemented with
HTTP/3 streams as defined in [[WEB-TRANSPORT-HTTP3]]. Datagrams are
implemented with QUIC datagrams as defined in [[WEB-TRANSPORT-HTTP3]].
[ Constructor (DOMString url), Exposed=Window] interface Http3Transport { }; Http3Transport includes UnidirectionalStreamsTransport; Http3Transport includes BidirectionalStreamsTransport; Http3Transport includes DatagramTransport; Http3Transport includes WebTransport;
Http3Transport
constructor is invoked,
the user agent MUST run the
following steps:
Http3Transport
object with state "connecting".
OutgoingStream
objects, initialized to empty.
IncomingStream
objects, initialized to empty.
Uint8Array
, initialized to empty.
Promise<sequence<Uint8Array>>?
,
initialized to null.
"failed"
and abort these steps.
"failed"
and abort these steps.
"connected"
and abort these steps.
Http3Transport
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
url | DOMString |
✘ | ✘ | The url specifying the host to connect to and the path to pass to it. |
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.
All of the transport protocols described in this document use either TLS [[TLS13]] or a semantically equivalent protocol, thus providing all of the security properties of TLS, including confidentiality and integrity of the traffic. Both QuicTransport and Http3Transport use the same certificate verification mechanism as outbound HTTP requests, thus relying on the same public key infrastructure for authentication of the remote server. In WebTransport, certificate verification errors are fatal; no interstitial allowing bypassing certificate validation is available.
WebTransport by itself does not create any new unique identifiers or new ways to persistently store state, nor does it automatically expose any of the existing persistent state to the server. For instance, none of the transports defined in this document automatically send cookies, support HTTP authentication or caching invalidation mechanisms. Since they use TLS, they may support TLS session tickets, which could be used by the server (though not by passive network observers) to correlate different connections from the same client. This is not specific to WebTransport by itself, but rather an inherent property of all TLS-based protocols; thus, this is out-of-scope for this specification.
WebTransport imposes a common set of requirements on all of the protocols, described in [[WEB-TRANSPORT-OVERVIEW]]. Notable ones include:
Protocol security considersations related to the individual transports are described in the Security Considerations sections of the corresponding protocol documents, [[WEB-TRANSPORT-QUIC]] and [[WEB-TRANSPORT-HTTP3]].
Networking APIs can be commonly used to scan the local network for available hosts, and thus be used for fingerprinting and other forms of attacks. WebTransport follows the WebSocket approach to this problem: the specific connection error is not returned until an endpoint is verified to be a WebTransport endpoint; thus, the Web application cannot distinguish between a non-existing endpoint and the endpoint that is not willing to accept connections from the Web.
The following events fire on transport objects:
Event name | Interface | Fired when... |
---|---|---|
error |
ErrorEvent |
The WebTransport object has encountered an error. |
statechange |
Event |
The WebTransportState changed. |
receivestream |
ReceiveStreamEvent |
A new ReceiveStream is dispatched to the
script in response to the remote peer creating a send-only stream and
sending data on it. Prior to receivestream
firing, the ReceiveStream is added to
WebTransport 's [[\IncomingStreams]]
internal slot. |
bidirectionalstream |
BidirectionalStreamEvent |
A new BidirectionalStream is dispatched to the
script in response to the remote peer creating a bidirectional stream and
sending data on it. Prior to bidirectionalstream
firing, the BidirectionalStream is added to the
WebTransport 's [[\IncomingStreams]]
and [[\OutgoingStreams]] internal slots. |
Unreliable delivery can be achieved by creating many streams with retransmissions disabled, each transporting a single small message.
let transport = getTransport(); let messages = getMessages(); for (msg in messages) { transport.createSendStream({disableRetransmissions: true}).write({data: msg, finished: true}); }
Sending a buffer of datagrams can be achieved by using the
sendDatagram
and readyToSendDatagram
methods. In
the following example datagrams are only sent if the
DatagramTransport
is ready to send, however the sending is not
blocked on the ACK promise returned from sendDatagram
(these are
ignored in this example).
const transport = getTransport(); const datagrams = getDatagramsToSend(); datagrams.forEach((datagram) => { await transport.readyToSendDatagram(); transport.sendDatagram(datagram); });
Sending 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 transport = getTransport(); setInterval(() => { transport.sendDatagram(createDatagram()); }, 100);
Receiving datagrams can be achieved by calling
receiveDatagrams()
method, remembering to check for null values
indicating that packets are not being processed quickly enough.
const transport = getTransport(); const datagrams = await transport.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.