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.

Introduction

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.

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]].

QuicTransportBase Interface

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.

Overview

An QuicTransportBase instance can be associated to one or more QuicBidirectionalStream, QuicSendStream, or QuicReceiveStream instances.

Interface Definition

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;
};

Attributes

state of type QuicTransportState, readonly

The current state of the QUIC transport. On getting, it MUST return the value of the [[\QuicTransportState]] internal slot.

maxDatagramSize of type unsigned short, readonly

The maximum size data that may be passed to sendDatagram.

onstatechange of type EventHandler

This 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 EventHandler

This 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 EventHandler

This 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 EventHandler

This 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.

Methods

stop

Stops 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:

  1. Let transport be the QuicTransportBase on which stop is invoked.
  2. If transport's [[\QuicTransportState]] is "closed" then abort these steps.
  3. Set transport's [[\QuicTransportState]] to "closed".
  4. Let stopInfo be the first argument.
  5. Start the Immediate Close procedure by sending an CONNECTION_CLOSE frame with its error code value set to the value of stopInfo.errorCode and its reason value set to the value of stopInfo.reason.
No parameters.
Return type: void
Parameter Type Nullable Optional Description
stopInfo QuicTransportStopInfo
createBidirectionalStream

Creates an QuicBidirectionalStream object.

When createBidectionalStream is called, the user agent MUST run the following steps:

  1. Let transport be the QuicTransportBase on which createBidectionalStream is invoked.

  2. If transport's state is "closed" or "failed", immediately return a new rejected promise with a newly created InvalidStateError and abort these steps.

  3. 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.

  4. Let p be a new promise.

  5. Return p and continue the following steps in the background.

    1. Resolve p with a newly created QuicBidirectionalStream object, add the QuicBidirectionalStream to the transport when all of the following conditions are met:

      1. The transport's state has transitioned to "connected"
      2. Stream creation flow control is not being violated by exceeding the max stream limit set by the remote endpoint, as specified in [[QUIC-TRANSPORT]].
      3. p has not been settled

    2. Reject p with a newly created InvalidStateError when all of the following conditions are met:

      1. The transport's state transitions to "closed" or "failed"
      2. p has not been settled
No parameters.
createSendStream

Creates an QuicSendStream object.

When createSendStream is called, the user agent MUST run the following steps:

  1. Let transport be the QuicTransportBase on which createSendStream is invoked.

  2. If transport's state is "closed" or "failed", immediately return a new rejected promise with a newly created InvalidStateError and abort these steps.

  3. 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.

  4. Let p be a new promise.

  5. Return p and continue the following steps in the background.

    1. Resolve p with a newly created QuicSendStream object, add the QuicSendStream to the transport when all of the following conditions are met:

      1. The transport's state has transitioned to "connected"
      2. Stream creation flow control is not being violated by exceeding the max stream limit set by the remote endpoint, as specified in [[QUIC-TRANSPORT]].
      3. p has not been settled

    2. Reject p with a newly created InvalidStateError when all of the following conditions are met:

      1. The transport's state transitions to "closed" or "failed"
      2. p has not been settled
No parameters.
readyToSendDatagram

Returns 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:

  1. Let p be a new promise.

  2. Let transport be the QuicTransportBase on which readyToSendDatagram is invoked.

  3. Return p and continue the following steps in the background.

    1. If transport can send a datagram, imediately resolve p and abort these steps.

    2. If transport's state is "failed" or "closed" immediately reject p with a newly created InvalidStateError and abort these steps.

    3. If transport is blocked from sending a datagram due to congestion control, resolve p when transport is no longer blocked.

    4. reject p with a newly created InvalidStateError if the transport's state transitions to "failed" or "closed".

No parameters.
Return type: Promise<void>
sendDatagram

Sends a datagram as defined by [[QUIC-DATAGRAM]].

When sendDatagram is called, the user agent MUST run the following steps:

  1. Let data be the first argument.
  2. Let transport be the QuicTransportBase on which sendDatagram is invoked.

  3. If transport's state is not connected return a promise rejected with a newly created InvalidStateError and abort these steps.

  4. If data is too large to fit into a datagram, return a promise rejected with a newly created InvalidArgumentError and abort these steps.

  5. 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.

  6. Let p be a new promise.

  7. Return p and continue the following steps in the background.

    1. Send data in a QUIC datagram.

    2. When an ack is received for the sent datagram, resolve p with true.

    3. When the datagram is detemined to be lost, resolve p with false.

Parameter Type Nullable Optional Description
data Uint8Array
Return type: 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.

Return type: Promise<sequence<Uint8Array>>

Procedures

Add QuicBidirectionalStream to the QuicTransport

To add the QuicBidirectionalStream to the QuicTransportBase run the following steps:

  1. Let stream be the newly created QuicBidirectionalStream object.

  2. Add stream to transport's [[\QuicTransportReadableStreams]] internal slot.

  3. Add stream to transport's [[\QuicTransportWritableStreams]] internal slot.

  4. Continue the following steps in the background.

  5. Create stream's associated underlying data transport.

Add QuicSendStream to the QuicTransportBase

To add the QuicSendStream to the QuicTransportBase run the following steps:

  1. Let stream be the newly created QuicSendStream object.

  2. Add stream to transport's [[\QuicTransportWritableStreams]] internal slot.

  3. Continue the following steps in the background.

  4. Create stream's associated underlying data transport.

QuicStreamParameters Dictionary

The QuicStreamParameters dictionary includes information relating to QUIC stream configuration.

dictionary QuicStreamParameters {
             bool disableRetransmissions = false;
};

Dictionary QuicStreamParameters Members

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.

ReceiveStreamEvent

The receivestream event uses the ReceiveStreamEvent interface.

        [ Constructor (DOMString type, ReceiveStreamEventInit eventInitDict), Exposed=Window]
interface ReceiveStreamEvent : Event {
    readonly        attribute QuicReceiveStream stream;
};

Constructors

ReceiveStreamEvent
Parameter Type Nullable Optional Description
type DOMString
eventInitDict ReceiveStreamEventInit

Attributes

stream of type QuicReceiveStream, readonly

The 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;
};

Dictionary ReceiveStreamEventInit Members

stream of type QuicReceiveStream

The QuicReceiveStream object associated with the event.

BidirectionalStreamEvent

The bidirectionalstream event uses the BidirectionalStreamEvent interface.

        [ Constructor (DOMString type, BidirectionalStreamEventInit eventInitDict), Exposed=Window]
interface BidirectionalStreamEvent : Event {
    readonly        attribute QuicBidirectionalStream stream;
};

Constructors

BidirectionalStreamEvent
Parameter Type Nullable Optional Description
type DOMString
eventInitDict BidirectionalStreamEventInit

Attributes

stream of type QuicBidirectionalStream, readonly

The 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;
};

Dictionary BidirectionalStreamEventInit Members

stream of type QuicBidirectionalStream

The QuicBidirectionalStream object associated with the event.

QuicTransportState Enum

QuicTransportState indicates the state of the QUIC transport.

enum QuicTransportState {
    "new",
    "connecting",
    "connected",
    "closed",
    "failed"
};
Enumeration description
new

The QuicTransportBase object has been created and has not started negotiating yet.

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 start()), incoming data can flow through.

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 stop() or receipt of a closing frame as described in [[QUIC-TRANSPORT]]. When the QuicTransportBase's internal [[\QuicTransportState]] slot transitions to closed the user agent MUST run the following steps:

  1. Let transport be the QuicTransportBase.
  2. For each QuicReadableStream in transport's [[\QuicTransportReadableStreams]] internal slot run the following:
    1. Let stream be the QuicReadableStream.
    2. Set stream's [[\Readable]] slot to false.
    3. Clear the stream's read buffer.
    4. Remove the stream from the transport's [[\QuicTransportReadableStreams]] internal slot.
  3. For each QuicWritableStream in transport's [[\QuicTransportWritableStreams]] internal slot run the following:
    1. Let stream be the QuicWritableStream.
    2. Set stream's [[\Writable]] slot to false.
    3. Clear the stream's write buffer.
    4. Remove the stream from the transport's [[\QuicTransportWritableStreams]] internal slot.
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 QuicTransportBase's internal [[\QuicTransportState]] slot transitions to failed the user agent MUST run the following steps:

  1. Let transport be the QuicTransportBase.
  2. For each QuicReadableStream in transport's [[\QuicTransportReadableStreams]] internal slot run the following:
    1. Let stream be the QuicReadableStream.
    2. Set stream's [[\Readable]] slot to false.
    3. Clear the stream's read buffer.
    4. Remove the stream from the transport's [[\QuicTransportReadableStreams]] internal slot.
  3. For each QuicWritableStream in transport's [[\QuicTransportWritableStreams]] internal slot run the following:
    1. Set stream's [[\Writable]] slot to false.
    2. Clear the stream's write buffer.
    3. Remove the stream from the transport's [[\QuicTransportWritableStreams]] internal slot.

QuicTransportStopInfo Dictionary

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 = "";
        };
        

Dictionary QuicTransportStopInfo Members

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

QuicTransport Interface

The QuicTransportBase is a subclass of QuicTransportBase focused on client/server use cases.

Interface Definition

        [ Constructor (DOMString host, unsigned short port), Exposed=Window]
interface QuicTransport : QuicTransportBase {
};

Constructors

When the QuicTransport constructor is invoked, the user agent MUST run the following steps:
  1. If port is 0, throw an NotSupportedError and abort these steps.
  2. Let quictransport be a newly constructed QuicTransport object.
  3. Let quictransport have a [[\QuicTransportWritableStreams]] internal slot representing a sequence of QuicWritableStream objects, initialized to empty.
  4. Let quictransport have a [[\QuicTransportReadableStreams]] internal slot representing a sequence of QuicReadableStream objects, initialized to empty.
  5. Let quictransport have a [[\QuicTransportState]] internal slot, initialized to "connecting".
  6. Let quictransport have a [[\QuicTransportReceivedDatagrams]] internal slot representing a queue of Uint8Array, initialized to empty.
  7. Let quictransport have a [[\QuicTransportReceiveDatagramsPromise]] internal slot representing a Promise<sequence<Uint8Array>>?, initialized to null.
  8. Run these steps in parallel:
    1. Establish a QUIC connection to the address identified by the given host and port. During connection establishment, use of this API must be indicated by selecting the ALPN [[!ALPN]] token "wq" in the crypto handshake and including a QUIC transport parameter with ID web_client(0x333C) and empty value.
    2. If the connection fails, set quictransport's [[\QuicTransportState]] internal slot to "failed" and abort these steps.
    3. Let joinedAcceptedOrigins be the QUIC transport parameter provided by the server with ID web_accepted_origins(0x333A). If the transport parameter is absent, set quictransport's [[\QuicTransportState]] internal slot to "failed" and abort these steps.
    4. Let serializedAcceptedOrigins be joinedAcceptedOrigins split by the separator ",".
    5. Let serializedOrigin be quictransport's relevant settings object's origin, serialized.
    6. If serializedOrigin is a member of serializedAcceptedOrigins or joinedAcceptedOrigins is equal to "*", set quictransport's [[\QuicTransportState]] internal slot to "connected" and abort these steps.
    7. Set quictransport's [[\QuicTransportState]] internal slot to "failed".
  9. Return quictransport.
QuicTransport
Parameter Type Nullable Optional Description
host DOMString The host to connect to.
port unsigned short The port to connect to.

QUIC Stream API

The QUIC Stream API includes information relating to a QUIC stream.

Overview

QuicBidirectionalStream, QuicSendStream, and QuicReceiveStream instances are associated to a QuicTransportBase instance.

Operation

An QuicBidirectionalStream can be created in the following ways:

  1. Using the QuicTransportBase's createBidirectionalStream method.
  2. Getting a bidirectionalstream event on the QuicTransportBase.

An QuicSendStream can be created in the following ways:

  1. Using the QuicTransportBase's createSendStream method.

An QuicReceiveStream can be created in the following ways:

  1. Getting a receivestream event on the QuicTransportBase.

Interface Mixin QuicWritableStream

        [ 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);
        };
        

Overview

The QuicWritableStream will initialize with the following:

  1. Let stream be the QuicWritableStream.
  2. Let stream have a [[\Writable]] internal slot initialized to true.
  3. Let stream have a [[\WriteBufferedAmount]] internal slot initialized to zero.

Attributes

writable of type boolean readonly

The 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, readonly

The 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 readonly

The 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:

  1. Let stream be the QuicWritableStream object.
  2. Set stream's [[\Writable]] slot to false.
  3. Clear the stream's write buffer.
  4. Let transport be the QuicTransportBase, which the stream was created from.
  5. Remove the stream from the transport's [[\QuicTransportWritableStreams]] internal slot.
  6. resolve the promise with the resulting QuicStreamAbortInfo with the errorCode set to the value from the STOP_SENDING frame.

Methods

write

Writes 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:

  1. Let data be the first argument.
  2. Let stream be the QuicWritableStream object on which data is to be sent.
  3. if length of data.data is 0 and data.finished is false, throw a NotSupportedError and abort these steps.
  4. If stream's [[\Writable]] slot is false, throw an InvalidStateError and abort these steps.
  5. Increase the value of stream's [[\WriteBufferedAmount]] slot by the length of data.data in bytes.
  6. Queue data.data for transmission on stream's underlying data transport.
  7. if data.finish is set to true, run the following:
    1. Queue a STREAM frame with the FIN bit set.
    2. Set stream's [[\Writable]] slot to false.
    3. Let transport be the QuicTransportBase, which the stream was created from.
    4. Remove the stream from the transport's [[\QuicTransportWritableStreams]] internal slot.
    The actual transmission of data occurs in parallel. If sending data leads to a QUIC-level error, the application will be notified asynchronously through the QuicTransportBase's onerror EventHandler.
Parameter Type Nullable Optional Description
data QuicStreamWriteParameters
Return type: void
abortWriting

A 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:

  1. Let stream be the QuicWritableStream object which is about to abort writing.
  2. If stream's [[\Writable]] slot is false, throw an InvalidStateError and abort these steps.
  3. Set stream's [[\Writable]] slot to false.
  4. Clear the stream's write buffer.
  5. Let transport be the QuicTransportBase, which the stream was created from.
  6. Remove the stream from the transport's [[\QuicTransportWritableStreams]] internal slot.
  7. Let abortInfo be the first argument.
  8. Start the closing procedure by sending a RST_STREAM frame with its error code set to the value of abortInfo.errorCode.
Parameter Type Nullable Optional Description
abortInfo QuicStreamAbortInfo
Return type: 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:

  1. Let stream be the QuicWritableStream object on which waitForWriteBufferedAmountBelow was invoked.
  2. Let p be a new promise.
  3. If stream's [[\Writable]] slot is false, reject p with a newly created InvalidStateError and abort these steps.
  4. Let threshold be the first argument.
  5. When stream's [[\WriteBufferedAmount]]] slot decreases from above threshold to less than or equal to it, resolve p with undefined.
Parameter Type Nullable Optional Description
threshold unsigned long
Return type: Promise<void>

Interface Mixin QuicReadableStream

        [ 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);
        };
        

Overview

The QuicReadableStream will initialize with the following:

  1. Let stream be the QuicReadableStream.
  2. Let stream have a [[\Readable]] internal slot initialized to true.
  3. Let stream have a [[\ReadableAmount]] internal slot initialized to zero.

Attributes

readable of type boolean, readonly

The 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, readonly

The 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 readonly

The 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:

  1. Let stream be the QuicReadableStream object
  2. Set stream's [[\Readable]] slot to false.
  3. Clear the stream's read buffer.
  4. Let transport be the QuicTransportBase, which the stream was created from.
  5. Remove the stream from the transport's [[\QuicTransportReadableStreams]] internal slot.
  6. resolve the promise with the resulting QuicStreamAbortInfo with errorCode set to the value of the errror code from the RST_STREAM frame.

Methods

readInto

Reads 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:

  1. Let stream be the QuicReadableStream object on which readInto is invoked.
  2. If stream's [[\Readable]] slot is false, throw an InvalidStateError, then abort these steps.
  3. Let data be the first argument.
  4. Let result be the QuicStreamReadResult to be returned.
  5. If stream has finished reading, return result with amount set to 0 and finished set to true and abort these steps.
  6. Transfer data from the read buffer into data.
  7. Decrease the value of stream's [[\ReadableAmount]] slot by the length of data in bytes.
  8. Set result's amount to the size of data in bytes.
  9. If the data includes up to the FIN bit being read, then run the following steps:
    1. Set result's finished to true.
    2. Set the stream's [[\Readable]] slot to false.
    3. Let transport be the QuicTransportBase, which the stream was created from.
    4. Remove the stream from the transport's [[\QuicTransportReadableStreams]] internal slot.
  10. Else, set result's finished to false.
  11. Return result.
Parameter Type Nullable Optional Description
data Uint8Array
Return type: QuicStreamReadResult
abortReading

A 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:

  1. Let stream be the QuicReadableStream object which is about to abort reading.
  2. If stream's [[\Readable]] slot is false, throw an InvalidStateError and abort these steps.
  3. Set stream's [[\Readable]] slot to false.
  4. Clear the stream's read buffer.
  5. Let transport be the QuicTransportBase, which the stream was created from.
  6. Remove the stream from the transport's [[\QuicTransportReadableStreams]] internal slot.
  7. Let abortInfo be the first argument.
  8. Start the closing procedure by sending a STOP_SENDING frame with its error code set to the value of abortInfo.errorCode.
Parameter Type Nullable Optional Description
abortInfo QuicStreamAbortInfo
Return type: void
waitForReadable

waitForReadable 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:

  1. Let stream be the QuicReadableStream on which waitForReadable is invoked.
  2. Let p be a new promise.
  3. If stream's [[\Readable]] slot is false, reject p with a newly created InvalidStateError and abort these steps.
  4. Let amount be the first argument.
  5. Resolve p with undefined when any of the following conditions are met:
    1. The [[\ReadableAmount]] increases from below the value of amount to greater than or equal to it.
    2. stream receives a STREAM frame with the FIN bit set and [[\ReadableAmount]] is less than amount.
Parameter Type Nullable Optional Description
amount unsigned long
Return type: Promise<void>

Interface QuicStream

        [ Exposed=Window ]
        interface QuicStream {
            readonly attribute unsigned long long streamId;
            readonly attribute QuicTransportBase transport;
        };
        

Attributes

streamId of type unsigned long long, readonly

The readonly attribute referring to the ID of the QuicStream object.

transport of type QuicTransportBase, readonly

The readonly attribute referring to the related QuicTransportBase object.

Interface QuicBidirectionalStream

        [ Exposed=Window ]
        interface QuicBidirectionalStream : QuicStream {
        };
        QuicBidirectionalStream includes QuicWritableStream;
        QuicBidirectionalStream includes QuicReadableStream;
        

Interface QuicSendStream

        [ Exposed=Window ]
        interface QuicSendStream : QuicStream {
        };
        QuicSendStream includes QuicWritableStream;
        

Interface QuicReceiveStream

        [ Exposed=Window ]
        interface QuicReceiveStream : QuicStream {
        };
        QuicReceiveStream includes QuicReadableStream;
        

QuicStreamWriteParameters Dictionary

The QuicStreamWriteParameters dictionary includes information relating to the data to be written with QuicWritableStream.write.

dictionary QuicStreamWriteParameters {
             Uint8Array data;
             boolean finished = false;
        };
        

Dictionary QuicStreamWriteParameters Members

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.

QuicStreamReadResult Dictionary

The QuicStreamReadResult dictionary includes information relating to the result returned from readInto.

dictionary QuicStreamReadResult {
             unsigned long amount;
             boolean finished = false;
        };
        

Dictionary QuicStreamReadResult Members

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.

QuicStreamAbortInfo Dictionary

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;
        };
        

Dictionary QuicStreamAbortInfo Members

errorCode of type unsigned short.

The error code used in the RST_STREAM or STOP_SENDING frame. The default value of 0 means "STOPPING."

Privacy and Security Considerations

This section is non-normative; it specifies no new behaviour, but instead summarizes information already present in other parts of the specification.

Confidentiality of Communications

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.

Event summary

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.

Examples

Unreliable delivery

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

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

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

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
        }
      };
      

Change Log

This section will be removed before publication.

Acknowledgements

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.