This specification defines an API that allows web applications to talk to servers and devices that have their own protocols incompatible with those available on the web.

This is a work in progress. All contributions welcome.

{{TCPSocket}} interface

      [
        Exposed=(Window,DedicatedWorker),
        SecureContext,
        IsolatedContext
      ]
      interface TCPSocket {
        constructor(DOMString remoteAddress,
                    unsigned short remotePort,
                    optional TCPSocketOptions options = {});

        readonly attribute Promise<TCPSocketOpenInfo> opened;
        readonly attribute Promise<undefined> closed;

        Promise<undefined> close();
      };
    

Methods on this interface typically complete asynchronously, queuing work on the TCPSocket task source.

Instances of {{TCPSocket}} are created with the internal slots described in the following table:

Internal slot Initial value Description (non-normative)
[[\readable]] `null` A {{ReadableStream}} that receives data from the socket
[[\writable]] `null` A {{WritableStream}} that transmits data to the socket
[[\openedPromise]] `new Promise` A {{Promise}} used to wait for the socket to be opened. Corresponds to the {{TCPSocket/opened}} member.
[[\closedPromise]] `new Promise` A {{Promise}} used to wait for the socket to close or error. Corresponds to the {{TCPSocket/closed}} member.

constructor() method

The {{TCPSocket/constructor()}} steps are:
  1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=policy-controlled feature=] named "[=policy-controlled feature/direct-sockets=]", throw a "{{NotAllowedError}}" {{DOMException}}.
  2. If |options|["{{TCPSocketOptions/keepAliveDelay}}"] is less than 1,000, throw a {{TypeError}}.
  3. If |options|["{{TCPSocketOptions/sendBufferSize}}"] is equal to 0, throw a {{TypeError}}.
  4. If |options|["{{TCPSocketOptions/receiveBufferSize}}"] is equal to 0, throw a {{TypeError}}.
  5. Perform the following steps [=in parallel=].
    1. If |remoteAddress| resolves to an IP address belonging to the [=IP address space/private=] network address space and [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=policy-controlled feature=] named "[=policy-controlled feature/direct-sockets-private=]", [=queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPSocket task source=] to run the following steps:
      1. [=Reject=] the {{TCPSocket/[[openedPromise]]}} with a "{{NotAllowedError}}" {{DOMException}}.
      2. [=Reject=] the {{TCPSocket/[[closedPromise]]}} with a "{{NotAllowedError}}" {{DOMException}}.
    2. Invoke the operating system to open a TCP socket using the given |remoteAddress| and |remotePort| and the connection parameters (or their defaults) specified in |options|.
    3. If this fails for any other reason, [=queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPSocket task source=] to run the following steps:
      1. [=Reject=] the {{TCPSocket/[[openedPromise]]}} with a "{{NetworkError}}" {{DOMException}}.
      2. [=Reject=] the {{TCPSocket/[[closedPromise]]}} with a "{{NetworkError}}" {{DOMException}}.
    4. On success, [=queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPSocket task source=] to run the following steps:
      1. [=initialize TCPSocket readable stream|Initialize=] {{TCPSocket/[[readable]]}}.
      2. [=initialize TCPSocket writable stream|Initialize=] {{TCPSocket/[[writable]]}}.
      3. Let |openInfo:TCPSocketOpenInfo| be a new {{TCPSocketOpenInfo}}.
      4. Set |openInfo|["{{TCPSocketOpenInfo/readable}}"] to [=this=].{{TCPSocket/[[readable]]}}.
      5. Set |openInfo|["{{TCPSocketOpenInfo/writable}}"] to [=this=].{{TCPSocket/[[writable]]}}.
      6. Populate the remaining fields of |openInfo| using the information provided by the operating system: |openInfo|["{{TCPSocketOpenInfo/remoteAddress}}"], |openInfo|["{{TCPSocketOpenInfo/remotePort}}"], |openInfo|["{{TCPSocketOpenInfo/localAddress}}"] and |openInfo|["{{TCPSocketOpenInfo/localPort}}"].
      7. [=Resolve=] [=this=].{{TCPSocket/[[openedPromise]]}} with |openInfo|.

TCPSocketOptions dictionary

          enum SocketDnsQueryType {
            "ipv4",
            "ipv6"
          };

          dictionary TCPSocketOptions {
            [EnforceRange] unsigned long sendBufferSize;
            [EnforceRange] unsigned long receiveBufferSize;

            boolean noDelay = false;
            [EnforceRange] unsigned long keepAliveDelay;

            SocketDnsQueryType dnsQueryType;
          };
        
sendBufferSize member
The requested send buffer size, in bytes. If not specified, then platform-specific default value will be used.
receiveBufferSize member
The requested receive buffer size, in bytes. If not specified, then platform-specific default value will be used.
noDelay member
Enables the `TCP_NODELAY` option, disabling Nagle's algorithm.
No-Delay is disabled by default.
keepAliveDelay member
If specified, enables TCP Keep-Alive by setting `SO_KEEPALIVE` option on the socket to `true`. The way the actual delay is set is platform-specific:
  1. On Linux & ChromeOS `keepAliveDelay` is applied to `TCP_KEEPIDLE` and `TCP_KEEPINTVL`;
  2. On MacOS `keepAliveDelay` affects `TCP_KEEPALIVE`;
  3. On Windows `keepAliveDelay` is replicated to `keepalivetime` and `keepaliveinterval` of `SIO_KEEPALIVE_VALS`.
Keep-Alive is disabled by default.
dnsQueryType member
Indicates whether IPv4 or IPv6 record should be returned during DNS lookup. If omitted, the OS will select the record type(s) to be queried automatically depending on IPv4/IPv6 settings and reachability.

{{TCPSocket/[[readable]]}} attribute (internal)

The steps to initialize the TCPSocket readable stream are:
  1. Let |stream:ReadableStream| be a [=new=] {{ReadableStream}}.
  2. Let |pullAlgorithm| be the following steps:
    1. Let |desiredSize| be the [=ReadableStream/desired size to fill up to the high water mark=] for [=this=].{{TCPSocket/[[readable]]}}.
    2. If [=this=].{{TCPSocket/[[readable]]}}'s [=ReadableStream/current BYOB request view=] is non-null, then set |desiredSize| to [=this=].{{TCPSocket/[[readable]]}}'s [=ReadableStream/current BYOB request view=]'s [=BufferSource/byte length=].
    3. Run the following steps in parallel:
      1. Invoke the operating system to read up to |desiredSize| bytes from the socket, placing the result in the [=byte sequence=] |bytes|.
      2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPSocket task source=] to run the following steps:
        1. If the connection was closed gracefully, run the following steps:
          1. Invoke [=ReadableStream/close=] on [=this=].{{TCPSocket/[[readable]]}}.
          2. Invoke the steps to [=handle closing the TCPSocket readable stream=].
          This is triggered by the peer sending a packet with the FIN flag set and is typically indicated by the operating system returning 0 bytes when asked for more data from the socket.
        2. If no errors were encountered, then:
          1. If [=this=].{{TCPSocket/[[readable]]}}'s [=ReadableStream/current BYOB request view=] is non-null, then [=ArrayBufferView/write=] |bytes| into [=this=].{{TCPSocket/[[readable]]}}'s [=ReadableStream/current BYOB request view=], and set |view| to [=this=].{{TCPSocket/[[readable]]}}'s [=ReadableStream/current BYOB request view=].
          2. Otherwise, set |view| to the result of [=ArrayBufferView/create|creating=] a {{Uint8Array}} from |bytes| in [=this=]'s [=relevant Realm=].
          3. [=ReadableStream/Enqueue=] |view| into [=this=].{{TCPSocket/[[readable]]}}.
        3. If a network or operating system error was encountered, invoke [=ReadableStream/error=] on [=this=].{{TCPSocket/[[readable]]}} with a "{{NetworkError}}" {{DOMException}} and invoke the steps to [=handle closing the TCPSocket readable stream=].
    4. Return [=a promise resolved with=] `undefined`.
  3. Let |cancelAlgorithm| be the following steps:
    1. Invoke the steps to [=handle closing the TCPSocket readable stream=].
    2. Return [=a promise resolved with=] `undefined`.
  4. [=ReadableStream/Set up with byte reading support=] |stream| with [=ReadableStream/set up with byte reading support/pullAlgorithm=] set to |pullAlgorithm|, [=ReadableStream/set up with byte reading support/cancelAlgorithm=] set to |cancelAlgorithm|, and [=ReadableStream/set up with byte reading support/highWaterMark=] set to an implementation-defined value.
  5. Set [=this=].{{TCPSocket/[[readable]]}} to |stream|.
To handle closing the TCPSocket readable stream perform the following steps:
  1. If [=this=].{{TCPSocket/[[writable]]}} is active, abort these steps.
  2. Run the following steps [=in parallel=].
    1. Invoke the operating system to close the socket.
    2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPSocket task source=] to run the following steps:
      • If [=this=].{{TCPSocket/[[writable]]}} is errored, [=reject=] [=this=].{{TCPSocket/[[closedPromise]]}} with [=this=].{{TCPSocket/[[writable]]}}.`[[storedPromise]]`.
      • Otherwise, if [=this=].{{TCPSocket/[[readable]]}} is errored, [=reject=] [=this=].{{TCPSocket/[[closedPromise]]}} with [=this=].{{TCPSocket/[[readable]]}}.`[[storedPromise]]`.
      • Otherwise, [=resolve=] [=this=].{{TCPSocket/[[closedPromise]]}} with `undefined`.

{{TCPSocket/[[writable]]}} attribute (internal)

The steps to initialize the TCPSocket writable stream are:
  1. Let |stream:WritableStream| be a [=new=] {{WritableStream}}.
  2. Let |signal:AbortSignal| be |stream|'s [=WritableStream/signal=].
  3. Let |writeAlgorithm| be the following steps, given |chunk|:
    1. Let |promise:Promise| be [=a new promise=].
    2. Assert: |signal| is not [=AbortSignal/aborted=].
    3. If |chunk| cannot be [=converted to an IDL value=] of type {{BufferSource}}, reject |promise| with a {{TypeError}} and return |promise|. Otherwise, save the result of the conversion in |source:BufferSource|.
    4. [=Get a copy of the buffer source=] |source| and save the result in |bytes|.
    5. [=In parallel=], run the following steps:
      1. Invoke the operating system to write |bytes| to the socket.
        The operating system may return from this operation once |bytes| has been queued for transmission rather than after it has been transmitted.
      2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPSocket task source=] to run the following steps:
        1. If the chunk was successfully written, [=resolve=] |promise| with `undefined`.
          [[STREAMS]] specifies that |writeAlgorithm| will only be invoked after the {{Promise}} returned by a previous invocation of this algorithm has resolved. For efficiency an implementation is allowed to resolve this {{Promise}} early in order to coalesce multiple chunks waiting in the {{WritableStream}}'s internal queue into a single request to the operating system.
        2. If a network or operating system error was encountered:
          1. [=Reject=] |promise| with a "{{NetworkError}}" {{DOMException}}.
          2. Invoke the steps to [=handle closing the TCPSocket writable stream=].
        3. If |signal| is [=AbortSignal/aborted=], [=reject=] |promise| with |signal|'s [=AbortSignal/abort reason=].
    6. Return |promise|.
  4. Let |abortAlgorithm| be the following steps:
    1. Let |promise| be [=a new promise=].
    2. Run the following steps [=in parallel=]:
      1. Invoke the operating system to shutdown the socket for writing.
      2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPSocket task source=] to run the following steps:
        1. Invoke the steps to [=handle closing the TCPSocket writable stream=].
        2. [=Resolve=] |promise| with `undefined`.
    3. Return |promise|.
  5. Let |closeAlgorithm| be the following steps:
    1. Let |promise| be [=a new promise=].
    2. Run the following steps [=in parallel=].
      1. Invoke the operating system to shutdown the socket for writing.
      2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPSocket task source=] to run the following steps:
        1. Invoke the steps to [=handle closing the TCPSocket writable stream=].
        2. If |signal| is [=AbortSignal/aborted=], [=reject=] |promise| with |signal|'s [=AbortSignal/abort reason=].
        3. [=Resolve=] |promise| with `undefined`.
    3. Return |promise|.
  6. [=WritableStream/Set up=] |stream| with [=WritableStream/set up/writeAlgorithm=] set to |writeAlgorithm|, [=WritableStream/set up/abortAlgorithm=] set to |abortAlgorithm|, [=WritableStream/set up/closeAlgorithm=] set to |closeAlgorithm|, [=WritableStream/set up/highWaterMark=] set to an implementation-defined value.
  7. [=AbortSignal/Add=] the following abort steps to |signal|:
    1. Cause any invocation of the operating system to write to the socket to return as soon as possible no matter how much data has been written.
  8. Set [=this=].{{TCPSocket/[[writable]]}} to |stream|.
To handle closing the TCPSocket writable stream perform the following steps:
  1. If [=this=].{{TCPSocket/[[readable]]}} is active, abort these steps.
  2. Run the following steps [=in parallel=].
    1. Invoke the operating system to close the socket.
    2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPSocket task source=] to run the following steps:
      • If [=this=].{{TCPSocket/[[readable]]}} is errored, [=reject=] [=this=].{{TCPSocket/[[closedPromise]]}} with [=this=].{{TCPSocket/[[readable]]}}.`[[storedPromise]]`.
      • Otherwise, if [=this=].{{TCPSocket/[[writable]]}} is errored, [=reject=] [=this=].{{TCPSocket/[[closedPromise]]}} with [=this=].{{TCPSocket/[[writable]]}}.`[[storedPromise]]`.
      • Otherwise, [=resolve=] [=this=].{{TCPSocket/[[closedPromise]]}} with `undefined`.

opened attribute

When called, returns the [=this=].{{TCPSocket/[[openedPromise]]}}.

TCPSocketOpenInfo dictionary

          dictionary TCPSocketOpenInfo {
            ReadableStream readable;
            WritableStream writable;

            DOMString remoteAddress;
            unsigned short remotePort;

            DOMString localAddress;
            unsigned short localPort;
          };
        
readable member
The readable side of the socket. Set to {{TCPSocket/[[readable]]}}.
writable member
The writable side of the socket. Set to {{TCPSocket/[[writable]]}}.
remoteAddress member
Resolved remote IP address that the socket is connected to.
remotePort member
Remote port that the socket is connected to.
localAddress member
Local IP address that the socket is bound to.
localPort member
Local port that the socket is bound to.

closed attribute

When called, returns the [=this=].{{TCPSocket/[[closedPromise]]}}.

close() method

The {{TCPSocket/close()}} method steps are:
  1. If [=this=].{{TCPSocket/[[openedPromise]]}} is rejected or not yet resolved, [=reject=] with "{{InvalidStateError}}" {{DOMException}}.
  2. If [=this=].{{TCPSocket/[[closedPromise]]}} is settled, return [=this=].{{TCPSocket/[[closedPromise]]}}.
  3. If [=this=].{{TCPSocket/[[readable]]}} or [=this=].{{TCPSocket/[[writable]]}} are locked, [=reject=] with "{{InvalidStateError}}" {{DOMException}}.
  4. Let |cancelPromise:Promise| be the result of invoking [=ReadableStream/cancel=] on [=this=].{{TCPSocket/[[readable]]}}.
  5. Set |cancelPromise|.[[\PromiseIsHandled]] to true.
  6. Let |abortPromise:Promise| be the result of invoking [=WritableStream/abort=] on [=this=].{{TCPSocket/[[writable]]}}.
  7. Set |abortPromise|.[[\PromiseIsHandled]] to true.
  8. Return [=this=].{{TCPSocket/[[closedPromise]]}}.

{{UDPSocket}} interface

      [
        Exposed=(Window,DedicatedWorker),
        SecureContext,
        IsolatedContext
      ]
      interface UDPSocket {
        constructor(optional UDPSocketOptions options = {});

        readonly attribute Promise<UDPSocketOpenInfo> opened;
        readonly attribute Promise<undefined> closed;

        Promise<undefined> close();
      };
    
Methods on this interface typically complete asynchronously, queuing work on the UDPSocket task source.

Instances of {{UDPSocket}} are created with the internal slots described in the following table:

Internal slot Initial value Description (non-normative)
[[\readable]] `null` A {{ReadableStream}} that receives data from the socket
[[\writable]] `null` A {{WritableStream}} that transmits data to the socket
[[\openedPromise]] `new Promise` A {{Promise}} used to wait for the socket to be opened. Corresponds to the {{UDPSocket/opened}} member.
[[\closedPromise]] `new Promise` A {{Promise}} used to wait for the socket to close or error. Corresponds to the {{UDPSocket/closed}} member.

constructor() method

{{UDPSocket}} can operate in either {{UDPSocket/connected}} or {{UDPSocket/bound}} mode which is decided based on the provided set of constructor options. The {{UDPSocket/constructor()}} steps are:
  1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=policy-controlled feature=] named "[=policy-controlled feature/direct-sockets=]", throw a "{{NotAllowedError}}" {{DOMException}}.
  2. If any of |options|["{{UDPSocketOptions/multicastTimeToLive}}"], |options|["{{UDPSocketOptions/multicastLoopback}}"], or |options|["{{UDPSocketOptions/multicastAllowAddressSharing}}"] is specified, and [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=policy-controlled feature=] named "[=policy-controlled feature/direct-sockets-multicast=]", throw a "{{NotAllowedError}}" {{DOMException}}.
  3. If only one of |options|["{{UDPSocketOptions/remoteAddress}}"] and |options|["{{UDPSocketOptions/remotePort}}"] is specified, throw a {{TypeError}}.
  4. Alternatively, if both |options|["{{UDPSocketOptions/remoteAddress}}"] and |options|["{{UDPSocketOptions/remotePort}}"] are specified, assume {{UDPSocket/connected}} {{UDPSocket/mode}}.
  5. If |options|["{{UDPSocketOptions/localPort}}"] is equal to 0 or specified without |options|["{{UDPSocketOptions/localAddress}}"], throw a {{TypeError}}.
  6. If |options|["{{UDPSocketOptions/localAddress}}"] is specified:
    1. If {{UDPSocket/connected}} {{UDPSocket/mode}} was previously inferred, throw a {{TypeError}}.
    2. If |options|["{{UDPSocketOptions/localAddress}}"] is not a valid IP address, throw a {{TypeError}}.
    3. Assume {{UDPSocket/bound}} {{UDPSocket/mode}}.
  7. If no {{UDPSocket/mode}} has been inferred at this point, throw a {{TypeError}}.
  8. If |options|["{{UDPSocketOptions/dnsQueryType}}"] is specified in {{UDPSocket/bound}} {{UDPSocket/mode}}, throw a {{TypeError}}.
  9. If |options|["{{UDPSocketOptions/ipv6Only}}"] is specified:
    1. If inferred {{UDPSocket/mode}} is {{UDPSocket/connected}}, throw a {{TypeError}}.
    2. If |options|["{{UDPSocketOptions/localAddress}}"] is not equal to the IPv6 unspecified address (`::`), throw a {{TypeError}}.
  10. If |options|["{{UDPSocketOptions/sendBufferSize}}"] is equal to 0, throw a {{TypeError}}.
  11. If |options|["{{UDPSocketOptions/receiveBufferSize}}"] is equal to 0, throw a {{TypeError}}.
  12. Perform the following steps [=in parallel=].
    1. If the inferred {{UDPSocket/mode}} is {{UDPSocket/connected}} and |remoteAddress| resolves to an IP address belonging to the [=IP address space/private=] network address space and [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=policy-controlled feature=] named "[=policy-controlled feature/direct-sockets-private=]", [=queue a global task=] on the [=relevant global object=] of [=this=] using the [=UDPSocket task source=] to run the following steps:
      1. [=Reject=] the {{UDPSocket/[[openedPromise]]}} with a "{{NotAllowedError}}" {{DOMException}}.
      2. [=Reject=] the {{UDPSocket/[[closedPromise]]}} with a "{{NotAllowedError}}" {{DOMException}}.
    2. If the inferred {{UDPSocket/mode}} is {{UDPSocket/bound}} and either [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=policy-controlled feature=] named "[=policy-controlled feature/direct-sockets-private=]" or the requested |localPort| is less than 1024, [=queue a global task=] on the [=relevant global object=] of [=this=] using the [=UDPSocket task source=] to run the following steps:
      1. [=Reject=] the {{UDPSocket/[[openedPromise]]}} with a "{{NotAllowedError}}" {{DOMException}}.
      2. [=Reject=] the {{UDPSocket/[[closedPromise]]}} with a "{{NotAllowedError}}" {{DOMException}}.
      While these conditions could technically be checked at construction time, they're deliberately addressed here to unify the behavior with {{UDPSocket/connected}} {{UDPSocket/mode}}.
    3. Invoke the operating system to open a UDP socket using the inferred {{UDPSocket/mode}} and the parameters (or their defaults) specified in |options|.
    4. If this fails for any reason, [=queue a global task=] on the [=relevant global object=] of [=this=] using the [=UDPSocket task source=] to run the following steps:
      1. [=Reject=] the {{UDPSocket/[[openedPromise]]}} with a "{{NetworkError}}" {{DOMException}}.
      2. [=Reject=] the {{UDPSocket/[[closedPromise]]}} with a "{{NetworkError}}" {{DOMException}}.
    5. On success, [=queue a global task=] on the [=relevant global object=] of [=this=] using the [=UDPSocket task source=] to run the following steps:
      1. [=initialize UDPSocket readable stream|Initialize=] {{UDPSocket/[[readable]]}}.
      2. [=initialize UDPSocket writable stream|Initialize=] {{UDPSocket/[[writable]]}}.
      3. Let |openInfo:UDPSocketOpenInfo| be a new {{UDPSocketOpenInfo}}.
      4. Set |openInfo|["{{UDPSocketOpenInfo/readable}}"] to [=this=].{{UDPSocket/[[readable]]}}.
      5. Set |openInfo|["{{UDPSocketOpenInfo/writable}}"] to [=this=].{{UDPSocket/[[writable]]}}.
      6. Populate the remaining fields of |openInfo| using the information provided by the operating system:
        • For {{UDPSocket/bound}} {{UDPSocket/mode}}, populate only |openInfo|["{{UDPSocketOpenInfo/localAddress}}"] and |openInfo|["{{UDPSocketOpenInfo/localPort}}"].
        • For {{UDPSocket/connected}} {{UDPSocket/mode}}, populate |openInfo|["{{UDPSocketOpenInfo/localAddress}}"] and |openInfo|["{{UDPSocketOpenInfo/localPort}}"] as well as |openInfo|["{{UDPSocketOpenInfo/remoteAddress}}"] and |openInfo|["{{UDPSocketOpenInfo/remotePort}}"].
      7. Resolve [=this=].{{UDPSocket/[[openedPromise]]}} with |openInfo|.

UDPSocketOptions dictionary

          dictionary UDPSocketOptions {
            DOMString remoteAddress;
            [EnforceRange] unsigned short remotePort;

            DOMString localAddress;
            [EnforceRange] unsigned short localPort;

            [EnforceRange] unsigned long sendBufferSize;
            [EnforceRange] unsigned long receiveBufferSize;

            SocketDnsQueryType dnsQueryType;
            boolean ipv6Only;

            [EnforceRange] octet multicastTimeToLive;
            boolean multicastLoopback;
            boolean multicastAllowAddressSharing;
          };
        
remoteAddress member
The remote IP address to connect the socket to.
remotePort member
The remote port to connect the socket to.
localAddress member
The local IP address to bind the socket to.
localPort member
The local port to bind the socket to. Leave this field empty to let the OS pick one on its own.
sendBufferSize member
The requested send buffer size, in bytes. If not specified, then platform-specific default value will be used.
receiveBufferSize member
The requested receive buffer size, in bytes. If not specified, then platform-specific default value will be used.
dnsQueryType member
Indicates whether IPv4 or IPv6 record should be returned during DNS lookup. If omitted, the OS will select the record type(s) to be queried automatically depending on IPv4/IPv6 settings and reachability.
This field can only be supplied in {{UDPSocket/connected}} {{UDPSocket/mode}}.
ipv6Only member
Enables or disables `IPV6_V6ONLY` to either restrict connections to IPv6 only or allow both IPv4/IPv6 connections.
This field can only be supplied in {{UDPSocket/bound}} {{UDPSocket/mode}} when `localAddress` is equal to the IPv6 unspecified address (`::`).
Leave this field empty to retain default platform-defined behavior (`true` on Windows and `false` on Posix).
multicastTimeToLive member
This option controls how far your multicast packets can travel across a network. Each time a packet passes through a router, its TTL value is decremented. If the TTL reaches zero, the packet is discarded. It corresponds to `IP_MULTICAST_TTL / IPV6_MULTICAST_HOPS` in Unix. The default value is 1, which restricts packets to the local network segment.
This option requires [=policy-controlled feature=] named "[=policy-controlled feature/direct-sockets-multicast=]".
multicastLoopback member
Sets whether multicast packets sent from the host will be looped back to local listeners on the same host. It corresponds to `IP_MULTICAST_LOOP / IPV6_MULTICAST_LOOP` in Unix. The default is true.
This option requires [=policy-controlled feature=] named "[=policy-controlled feature/direct-sockets-multicast=]".
multicastAllowAddressSharing member
Whether multicast ipAddress:localPort tuple reuse is allowed. This is useful for allowing multiple applications to listen on the same multicast group address and port for multicast messages, such as in device discovery protocols. It corresponds to `SO_REUSEADDR / SO_REUSEPORT` in Unix. The default is false.
This option requires [=policy-controlled feature=] named "[=policy-controlled feature/direct-sockets-multicast=]".

UDPMessage dictionary

{{UDPSocket/[[readable]]}} and {{UDPSocket/[[writable]]}} streams operate on {{UDPMessage}} objects.
          dictionary UDPMessage {
            BufferSource data;
            DOMString remoteAddress;
            unsigned short remotePort;
            SocketDnsQueryType dnsQueryType;
          };
        
data member
The user message represented as {{BufferSource}}.
For {{UDPSocket/[[readable]]}} the underlying type is always {{Uint8Array}}.
remoteAddress member
The remote address where the message came from or where it should be send to.
  • In {{UDPSocket/connected}} {{UDPSocket/mode}} this field is always unspecified; attempting to set it while writing will throw (see {{UDPSocket/[[writable]]}}).
  • In {{UDPSocket/bound}} {{UDPSocket/mode}} this field represents the remote host that this packet came from for {{UDPSocket/[[readable]]}} or instructs the socket about the destination host for {{UDPSocket/[[writable]]}}.
remotePort member
The remote port where the message came from or where it should be sent to.
  • In {{UDPSocket/connected}} {{UDPSocket/mode}} this field is always unspecified; attempting to set it while writing will throw (see {{UDPSocket/[[writable]]}}).
  • In {{UDPSocket/bound}} {{UDPSocket/mode}} this field represents the remote port that this packet came from for {{UDPSocket/[[readable]]}} or instructs the socket about the destination port for {{UDPSocket/[[writable]]}}.
dnsQueryType member
Indicates whether IPv4 or IPv6 record should be returned during DNS lookup. If omitted, the OS will select the record type(s) to be queried automatically depending on IPv4/IPv6 settings and reachability.
This field is always unset for {{UDPMessage}} instances received from {{UDPSocket/[[readable]]}} stream regardless of socket's operating {{UDPSocket/mode}}. For {{UDPSocket/[[writable]]}} this can only be specified in {{UDPSocket/bound}} {{UDPSocket/mode}}; attempting to set the field in {{UDPSocket/connected}} {{UDPSocket/mode}} will throw.

{{UDPSocket/[[readable]]}} attribute (internal)

The steps to initialize the UDPSocket readable stream are:
  1. Let |stream:ReadableStream| be a [=new=] {{ReadableStream}}.
  2. Let |pullAlgorithm| be the following steps:
    1. Let |desiredSize| be the [=ReadableStream/desired size to fill up to the high water mark=] for [=this=].{{UDPSocket/[[readable]]}}.
    2. Run the following steps in parallel:
      1. Invoke the operating system to provide up to |desiredSize| UDP packets from the socket.
      2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=UDPSocket task source=] to run the following steps for each received packet:
        1. If no errors were encountered, for each packet received run the following steps:
          1. Let |bytes| be a [=byte sequence=] containing the packet payload.
          2. Let |buffer| be a [=new=] {{ArrayBuffer}} created from |bytes|.
          3. Let |chunk| be a [=new=] {{Uint8Array}} view over |buffer|, who's length is the length of |bytes|.
          4. Let |message:UDPMessage| be a new {{UDPMessage}}.
          5. Set |message|["{{UDPMessage/data}}"] to |chunk|.
          6. If the socket is operating in {{UDPSocket/bound}} {{UDPSocket/mode}}:
            1. Set |message|["{{UDPMessage/remoteAddress}}"] to the source address of the packet.
            2. Set |message|["{{UDPMessage/remotePort}}"] to the source port of the packet.
          7. Invoke [=ReadableStream/enqueue=] on [=this=].{{UDPSocket/[[readable]]}} with |message|.
        2. If a network or operating system error was encountered, invoke [=ReadableStream/error=] on [=this=].{{UDPSocket/[[readable]]}} with a "{{NetworkError}}" {{DOMException}}, discard other packets and invoke the steps to [=handle closing the UDPSocket readable stream=].
    3. Return [=a promise resolved with=] `undefined`.
  3. Let |cancelAlgorithm| be the following steps:
    1. Invoke the steps to [=handle closing the UDPSocket readable stream=].
    2. Return [=a promise resolved with=] `undefined`.
  4. [=ReadableStream/Set up=] |stream| with [=ReadableStream/set up/pullAlgorithm=] set to |pullAlgorithm|, [=ReadableStream/set up/cancelAlgorithm=] set to |cancelAlgorithm|, [=ReadableStream/set up/highWaterMark=] [=ReadableStream/Set up=] |stream| with set to an implementation-defined value.
  5. Set [=this=].{{UDPSocket/[[readable]]}} to |stream|.
To handle closing the UDPSocket readable stream perform the following steps:
  1. If [=this=].{{UDPSocket/[[writable]]}} is active, abort these steps.
  2. Run the following steps [=in parallel=].
    1. Invoke the operating system to close the socket.
    2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=UDPSocket task source=] to run the following steps:
      • If [=this=].{{UDPSocket/[[writable]]}} is errored, [=reject=] [=this=].{{UDPSocket/[[closedPromise]]}} with [=this=].{{UDPSocket/[[writable]]}}.`[[storedPromise]]`.
      • Otherwise, if [=this=].{{UDPSocket/[[readable]]}} is errored, [=reject=] [=this=].{{UDPSocket/[[closedPromise]]}} with [=this=].{{UDPSocket/[[readable]]}}.`[[storedPromise]]`.
      • Otherwise, [=resolve=] [=this=].{{UDPSocket/[[closedPromise]]}} with `undefined`.

{{UDPSocket/[[writable]]}} attribute (internal)

The steps to initialize the UDPSocket writable stream are:
  1. Let |stream:WritableStream| be a [=new=] {{WritableStream}}.
  2. Let |signal:AbortSignal| be |stream|'s [=WritableStream/signal=].
  3. Let |writeAlgorithm| be the following steps, given |chunk|:
    1. Let |promise:Promise| be [=a new promise=].
    2. Assert: |signal| is not [=AbortSignal/aborted=].
    3. Let |message:UDPMessage| be a new {{UDPMessage}}.
    4. If |chunk| cannot be [=converted to an IDL value=] of type {{UDPMessage}}, reject |promise| with a {{TypeError}} and return |promise|. Otherwise, save the result of the conversion in |message|.
    5. If either |message|["{{UDPMessage/remoteAddress}}"], |message|["{{UDPMessage/remotePort}}"] or |message|["{{UDPMessage/dnsQueryType}}"] is specified in {{UDPSocket/connected}} {{UDPSocket/mode}}, reject |promise| with a {{TypeError}} and return |promise|.
    6. If either |message|["{{UDPMessage/remoteAddress}}"] or |message|["{{UDPMessage/remotePort}}"] is not specified in {{UDPSocket/bound}} {{UDPSocket/mode}}, reject |promise| with a {{TypeError}} and return |promise|.
    7. [=Get a copy of the buffer source=] |message|["{{UDPMessage/data}}"] and save the result in |bytes|.
    8. [=In parallel=], run the following steps:
      1. Invoke the operating system to send |bytes| to the socket.
        • In {{UDPSocket/connected}} {{UDPSocket/mode}} the data is routed to the address/port specified upon construction.
        • In {{UDPSocket/bound}} {{UDPSocket/mode}} the data is routed to |message|["{{UDPMessage/remoteAddress}}"] and |message|["{{UDPMessage/remotePort}}"]. |message|["{{UDPMessage/dnsQueryType}}"] can be optionally supplied to control whether DNS resolution routine returns an IPv4 or an IPv6 record.
        The operating system may return from this operation once |bytes| has been queued for transmission rather than after it has been transmitted.
      2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=UDPSocket task source=] to run the following steps:
        1. If the data was successfully written, [=resolve=] |promise| with `undefined`.
        2. If a network or operating system error was encountered:
          1. [=Reject=] |promise| with a "{{NetworkError}}" {{DOMException}}.
          2. Invoke the steps to [=handle closing the UDPSocket writable stream=].
        3. If |signal| is [=AbortSignal/aborted=], [=reject=] |promise| with |signal|'s [=AbortSignal/abort reason=].
    9. Return |promise|.
  4. Let |abortAlgorithm| be the following steps:
    1. Invoke the steps to [=handle closing the UDPSocket writable stream=].
    2. Return [=a promise resolved with=] `undefined`.
  5. Let |closeAlgorithm| be the following steps:
    1. Invoke the steps to [=handle closing the UDPSocket writable stream=].
    2. Return [=a promise resolved with=] `undefined`.
  6. [=WritableStream/Set up=] |stream| with [=WritableStream/set up/writeAlgorithm=] set to |writeAlgorithm|, [=WritableStream/set up/abortAlgorithm=] set to |abortAlgorithm|, [=WritableStream/set up/closeAlgorithm=] set to |closeAlgorithm|, [=WritableStream/set up/highWaterMark=] set to an implementation-defined value.
  7. [=AbortSignal/Add=] the following abort steps to |signal|:
    1. Cause any invocation of the operating system to write to the socket to return as soon as possible no matter how much data has been written.
  8. Set [=this=].{{UDPSocket/[[writable]]}} to |stream|.
To handle closing the UDPSocket writable stream perform the following steps:
  1. If [=this=].{{UDPSocket/[[readable]]}} is active, abort these steps.
  2. Run the following steps [=in parallel=].
    1. Invoke the operating system to close the socket.
    2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=UDPSocket task source=] to run the following steps:
      • If [=this=].{{UDPSocket/[[readable]]}} is errored, [=reject=] [=this=].{{UDPSocket/[[closedPromise]]}} with [=this=].{{UDPSocket/[[readable]]}}.`[[storedPromise]]`.
      • Otherwise, if [=this=].{{UDPSocket/[[writable]]}} is errored, [=reject=] [=this=].{{UDPSocket/[[closedPromise]]}} with [=this=].{{UDPSocket/[[writable]]}}.`[[storedPromise]]`.
      • Otherwise, [=resolve=] [=this=].{{UDPSocket/[[closedPromise]]}} with `undefined`.

opened attribute

When called, returns the [=this=].{{UDPSocket/[[openedPromise]]}}.

UDPSocketOpenInfo dictionary

          dictionary UDPSocketOpenInfo {
            ReadableStream readable;
            WritableStream writable;

            DOMString remoteAddress;
            unsigned short remotePort;

            DOMString localAddress;
            unsigned short localPort;

            MulticastController multicastController;
          };
        
readable member
The readable side of the socket. Set to {{UDPSocket/[[readable]]}}.
writable member
The writable side of the socket. Set to {{UDPSocket/[[writable]]}}.
remoteAddress member
Resolved remote IP address that the socket is communicating with.
remotePort member
Remote port that the socket is communicating with.
localAddress member
Local IP address that the socket is bound to.
localPort member
Local port that the socket is bound to.
multicastController member
An object to control multicast group membership for receiving packets. This member is only present if the socket is in {{UDPSocket/bound}} {{UDPSocket/mode}} and the document has [=policy-controlled feature=] named "[=policy-controlled feature/direct-sockets-multicast=]".

closed attribute

When called, returns the [=this=].{{UDPSocket/[[closedPromise]]}}.

close() method

The {{UDPSocket/close()}} method steps are:
  1. If [=this=].{{UDPSocket/[[openedPromise]]}} is rejected or not yet resolved, [=reject=] with "{{InvalidStateError}}" {{DOMException}}.
  2. If [=this=].{{UDPSocket/[[closedPromise]]}} is settled, return [=this=].{{UDPSocket/[[closedPromise]]}}.
  3. If [=this=].{{UDPSocket/[[readable]]}} or [=this=].{{UDPSocket/[[writable]]}} are locked, [=reject=] with "{{InvalidStateError}}" {{DOMException}}.
  4. Let |cancelPromise:Promise| be the result of invoking [=ReadableStream/cancel=] on [=this=].{{UDPSocket/[[readable]]}}.
  5. Set |cancelPromise|.[[\PromiseIsHandled]] as handled.
  6. Let |abortPromise:Promise| be the result of invoking [=WritableStream/abort=] on [=this=].{{UDPSocket/[[writable]]}}.
  7. Set |abortPromise|.[[\PromiseIsHandled]] as handled.
  8. Return [=this=].{{UDPSocket/[[closedPromise]]}}.

{{MulticastController}} interface

The {{MulticastController}} interface provides methods to join and leave multicast groups and to inspect which groups have been joined. An instance of this interface is obtained from the {{UDPSocketOpenInfo/multicastController}} member of the dictionary returned by the {{UDPSocket/opened}} promise. This member is only present if the socket is in {{UDPSocket/bound}} {{UDPSocket/mode}} and and [=this=]'s [=relevant global object=]'s [=associated Document=] is [=allowed to use=] the [=policy-controlled feature=] named "[=policy-controlled feature/direct-sockets-multicast=]".

      [
        Exposed=(Window, DedicatedWorker),
        SecureContext,
        IsolatedContext
      ]
      interface MulticastController {
        Promise<undefined> joinGroup(DOMString ipAddress);
        Promise<undefined> leaveGroup(DOMString ipAddress);
        readonly attribute FrozenArray<DOMString> joinedGroups;
      };
  

Methods on this interface typically complete asynchronously, queuing work on the [=UDPSocket task source=].

Instances of {{MulticastController}} are created with the internal slots described in the following table:

Internal slot Description (non-normative)
[[\socket]] The {{UDPSocket}} that this {{MulticastController}} manages multicast membership for.
[[\joinedGroups]] An set of the IP addresses of the multicast groups that have been successfully joined, ordered from the earliest joined multicast group to the latest.

joinGroup() method

The {{MulticastController/joinGroup(ipAddress)}} method joins the multicast group at the given `ipAddress` and the `localPort` it was bound to.

The {{MulticastController/joinGroup(ipAddress)}} method steps are:
  1. If `ipAddress` is not a valid IP address, throw a {{TypeError}}.
  2. If the socket has already joined or in the process of joining a multicast group with specified `ipAddress` throw an "`InvalidStateError`" {{DOMException}}.
  3. If the associated {{MulticastController/[[socket]]}} was closed or aborted, throw an "`InvalidStateError`" {{DOMException}}.
  4. Let `promise` be [=a new promise=].
  5. Perform the following steps [=in parallel=]:
    1. Invoke the operating system to join the multicast group specified by `ipAddress`.
    2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=UDPSocket task source=] to run the following steps:
      1. If the operating system returned a failure, [=reject=] `promise` with a "`NetworkError`" {{DOMException}} and abort these steps.
      2. Add `ipAddress` to {{MulticastController/[[joinedGroups]]}}.
      3. [=Resolve=] `promise` with `undefined`.
  6. Return `promise`.

leaveGroup() method

The {{MulticastController/leaveGroup(ipAddress)}} method leaves a multicast group previously joined via {{MulticastController/joinGroup(ipAddress)}}.

It is not necessary to leave joined multicast groups to clean up the resources. On the socket close, operating system will leave the groups automatically.
The {{MulticastController/leaveGroup(ipAddress)}} method steps are:
  1. If `ipAddress` is not a valid IP address, throw a {{TypeError}}.
  2. If the socket has never joined the multicast group at the `ipAddress`, already left it or in the process of leaving it, throw an "`InvalidStateError`" {{DOMException}}.
  3. If the associated {{MulticastController/[[socket]]}} was closed or aborted, throw an "`InvalidStateError`" {{DOMException}}.
  4. Let `promise` be [=a new promise=].
  5. Perform the following steps [=in parallel=]:
    1. Invoke the operating system to leave the multicast group specified by `ipAddress`.
    2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=UDPSocket task source=] to run the following steps:
      1. If the operating system returned a failure, [=reject=] `promise` with a "`NetworkError`" {{DOMException}} and abort these steps.
      2. Remove `ipAddress` from {{MulticastController/[[joinedGroups]]}}.
      3. [=Resolve=] `promise` with `undefined`.
  6. Return `promise`.

joinedGroups attribute

When read, the `joinedGroups` attribute returns a new `FrozenArray` containing the IP addresses in {{MulticastController/[[joinedGroups]]}} ordered from earliest joined multicast group to the latest.

{{TCPServerSocket}} interface

      [
        Exposed=(Window,DedicatedWorker),
        SecureContext,
        IsolatedContext
      ]
      interface TCPServerSocket {
        constructor(DOMString localAddress,
                    optional TCPServerSocketOptions options = {});

        readonly attribute Promise<TCPServerSocketOpenInfo> opened;
        readonly attribute Promise<undefined> closed;

        Promise<undefined> close();
      };
    

Methods on this interface typically complete asynchronously, queuing work on the TCPServerSocket task source.

Instances of {{TCPServerSocket}} are created with the internal slots described in the following table:

Internal slot Initial value Description (non-normative)
[[\readable]] `null` A {{ReadableStream}} used to accept incoming connections.
[[\openedPromise]] `new Promise` A {{Promise}} used to wait for the socket to be opened. Corresponds to the {{TCPServerSocket/opened}} member.
[[\closedPromise]] `new Promise` A {{Promise}} used to wait for the socket to close or error. Corresponds to the {{TCPServerSocket/closed}} member.

constructor() method

The {{TCPServerSocket/constructor()}} steps are:
  1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=policy-controlled feature=] named "[=policy-controlled feature/direct-sockets=]", throw a "{{NotAllowedError}}" {{DOMException}}.
  2. If |localAddress| is not a valid IP address, throw a {{TypeError}}.
  3. If |options|["{{TCPServerSocketOptions/localPort}}"] is equal to 0, throw a {{TypeError}}.
  4. If |options|["{{TCPServerSocketOptions/backlog}}"] is equal to 0, throw a {{TypeError}}.
  5. If |options|["{{TCPServerSocketOptions/ipv6Only}}"] is true but `localAddress` is not equal to the IPv6 unspecified address (`::`), throw a {{TypeError}}.
  6. Perform the following steps [=in parallel=].
    1. If the requested |localPort| is less than 32678, [=queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPServerSocket task source=] to run the following steps:
      1. [=Reject=] the {{TCPServerSocket/[[openedPromise]]}} with a "{{NotAllowedError}}" {{DOMException}}.
      2. [=Reject=] the {{TCPServerSocket/[[closedPromise]]}} with a "{{NotAllowedError}}" {{DOMException}}.
      While this condition could technically be checked at construction time, it's deliberately addressed here to allow for potentially loosening it with additional user-facing permissions.
    2. Invoke the operating system to open a TCP server socket using the given |localAddress| and the connection parameters (or their defaults) specified in |options|.
    3. If this fails for any reason, [=queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPServerSocket task source=] to run the following steps:
      1. [=Reject=] the {{TCPServerSocket/[[openedPromise]]}} with a "{{NetworkError}}" {{DOMException}}.
      2. [=Reject=] the {{TCPServerSocket/[[closedPromise]]}} with a "{{NetworkError}}" {{DOMException}}.
    4. On success, [=queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPServerSocket task source=] to run the following steps:
      1. [=initialize TCPServerSocket readable stream|Initialize=] {{TCPServerSocket/[[readable]]}}.
      2. Let |openInfo:TCPServerSocketOpenInfo| be a new {{TCPServerSocketOpenInfo}}.
      3. Set |openInfo|["{{TCPServerSocketOpenInfo/readable}}"] to [=this=].{{TCPServerSocket/[[readable]]}}.
      4. Populate the remaining fields of |openInfo| using the information provided by the operating system: |openInfo|["{{TCPServerSocketOpenInfo/localAddress}}"] and |openInfo|["{{TCPServerSocketOpenInfo/localPort}}"].
      5. [=Resolve=] [=this=].{{TCPServerSocket/[[openedPromise]]}} with |openInfo|.

TCPServerSocketOptions dictionary

          dictionary TCPServerSocketOptions {
            [EnforceRange] unsigned short localPort;
            [EnforceRange] unsigned long backlog;

            boolean ipv6Only;
          };
        
localPort member
The port to open the socket on.
Leave this field empty to let the OS pick one on its own.
backlog member
The size of the OS accept queue.
Leave this field empty to let the OS pick a reasonable platform-specific default.
ipv6Only member
Enables or disables `IPV6_V6ONLY` to either restrict connections to IPv6 only or allow both IPv4/IPv6 connections.
This field can only be supplied when `localAddress` is equal to the IPv6 unspecified address (`::`).
Leave this field empty to retain default platform-defined behavior (`true` on Windows and `false` on Posix).

{{TCPServerSocket/[[readable]]}} attribute (internal)

The steps to initialize the TCPServerSocket readable stream are:
  1. Let |stream:ReadableStream| be a [=new=] {{ReadableStream}}.
  2. Let |pullAlgorithm| be the following steps:
    1. Let |desiredSize| be the desired size of [=this=].{{TCPServerSocket/[[readable]]}}'s internal queue.
    2. Run the following steps in parallel:
      1. Invoke the operating system to accept up to |desiredSize| incoming connections.
      2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPServerSocket task source=] to run the following steps:
        1. If the connection was closed gracefully, run the following steps:
          1. Invoke [=ReadableStream/close=] on [=this=].{{TCPServerSocket/[[readable]]}}.
          2. Invoke the steps to [=handle closing the TCPServerSocket readable stream=].
        2. If no errors were encountered run the following steps:
          1. Let |tcpSocket| be a [=new=] {{TCPSocket}} accepted by the operating system.
          2. Invoke [=ReadableStream/enqueue=] on [=this=].{{TCPServerSocket/[[readable]]}} with |tcpSocket|.
        3. If a network or operating system error was encountered, invoke [=ReadableStream/error=] on [=this=].{{TCPServerSocket/[[readable]]}} with a "{{NetworkError}}" {{DOMException}} and invoke the steps to [=handle closing the TCPServerSocket readable stream=].
    3. Return [=a promise resolved with=] `undefined`.
  3. Let |cancelAlgorithm| be the following steps:
    1. Invoke the steps to [=handle closing the TCPServerSocket readable stream=].
    2. Return [=a promise resolved with=] `undefined`.
  4. [=ReadableStream/Set up=] |stream| with pullAlgorithm set to |pullAlgorithm|, cancelAlgorithm set to |cancelAlgorithm|, highWaterMark set to an implementation-defined value.
  5. Set [=this=].{{TCPServerSocket/[[readable]]}} to |stream|.
To handle closing the TCPServerSocket readable stream run the following steps [=in parallel=]:
  1. Invoke the operating system to close the socket.
  2. [=Queue a global task=] on the [=relevant global object=] of [=this=] using the [=TCPServerSocket task source=] to [=resolve=] [=this=].{{TCPServerSocket/[[closedPromise]]}} with `undefined`.

opened attribute

When called, returns the [=this=].{{TCPServerSocket/[[openedPromise]]}}.

TCPServerSocketOpenInfo dictionary

          dictionary TCPServerSocketOpenInfo {
            ReadableStream readable;

            DOMString localAddress;
            unsigned short localPort;
          };
        
readable member
The readable side of the socket. Set to {{TCPServerSocket/[[readable]]}}.
localAddress member
Local IP address that the socket is bound to.
localPort member
Local port that the socket is bound to.

closed attribute

When called, returns the [=this=].{{TCPServerSocket/[[closedPromise]]}}.

close() method

The {{TCPServerSocket/close()}} method steps are:
  1. If [=this=].{{TCPServerSocket/[[openedPromise]]}} is rejected or not yet resolved, [=reject=] with "{{InvalidStateError}}" {{DOMException}}.
  2. If [=this=].{{TCPServerSocket/[[closedPromise]]}} is settled, return [=this=].{{TCPServerSocket/[[closedPromise]]}}.
  3. If [=this=].{{TCPServerSocket/[[readable]]}} is locked, [=reject=] with "{{InvalidStateError}}" {{DOMException}}.
  4. Let |cancelPromise:Promise| be the result of invoking [=ReadableStream/cancel=] on [=this=].{{TCPServerSocket/[[readable]]}}.
  5. Set |cancelPromise|.[[\PromiseIsHandled]] to true.
  6. Return [=this=].{{TCPServerSocket/[[closedPromise]]}}.

Integrations

Permissions Policy

This specification defines a feature that controls whether {{TCPSocket}}, {{UDPSocket}} and {{TCPServerSocket}} classes may be created.

The feature name for this feature is "direct-sockets"`.

The default allowlist for this feature is `'none'`.

A document’s permission policy determines whether a `new TCPSocket(...)`, `new UDPSocket(...)` or `new TCPServerSocket(...)` call rejects with a {{"NotAllowedError"}} {{DOMException}}.

Permissions Policy (Private Network Access)

This specification defines a feature that controls whether {{TCPSocket}} and {{UDPSocket}} classes might connect to addresses belonging to the [=IP address space/private=] network address space.

The feature name for this feature is "direct-sockets-private"`.

The default allowlist for this feature is `'none'`.

A document’s permission policy determines whether a {{TCPSocket}} {{TCPSocket/[[openedPromise]]}} or {{UDPSocket}} {{UDPSocket/[[openedPromise]]}} promise rejects with a {{"NotAllowedError"}} {{DOMException}}.
  • For {{TCPSocket}}, the {{TCPSocket/[[openedPromise]]}} will be rejected if the resolved address belongs to the [=IP address space/private=] network address space.
  • For {{UDPSocket}} in {{UDPSocket/connected}} {{UDPSocket/mode}}, the {{UDPSocket/[[openedPromise]]}} will be rejected if the resolved address belongs to the [=IP address space/private=] network address space.
  • For {{UDPSocket}} in {{UDPSocket/bound}} {{UDPSocket/mode}}, the {{UDPSocket/[[openedPromise]]}} will be rejected unconditionally.

Permissions Policy (Multicast)

This specification defines a feature that controls whether an application can receive multicast packets using {{UDPSocket}} and {{MulticastController}}.

The feature name for this feature is "direct-sockets-multicast"`.

The default allowlist for this feature is `'none'`.

A document’s permission policy determines whether multicast-specific members of {{UDPSocketOptions}} can be used and whether the {{MulticastController}} interface is available.
  • If an application without the permission attempts to construct a {{UDPSocket}} with the {{UDPSocketOptions/multicastTimeToLive}}, {{UDPSocketOptions/multicastLoopback}}, or {{UDPSocketOptions/multicastAllowAddressSharing}} members set, the constructor will throw a "{{NotAllowedError}}" {{DOMException}}.
  • If an application without the permission successfully opens a {{UDPSocket}} in {{UDPSocket/bound}} mode, the returned {{UDPSocketOpenInfo}} dictionary will not contain the {{UDPSocketOpenInfo/multicastController}} member.

Security and privacy considerations