Abstract

This API provides interfaces to raw UDP sockets, TCP Client sockets and TCP Server sockets. As such, this requires a high level of trust in applications that use this API, since raw sockets can be used to work around the same origin security policy.

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document was produced by the System Applications Working Group. Members of this Working Group have agreed not to progress the TCP UDP Sockets API specification further as a Recommendation track document, electing instead to publish it as an informative Working Group Note under a permissive license with a view to enabling it to form the basis of further work by others, e.g. in a W3C Community Group.

Note

This specification is based the Streams API, [STREAMS]. Note that the Streams API is work in progress and any changes made to Streams may impact the TCP and UDP Socket API specification. However, it is the editor's ambition to continously update the TCP and UDP API specification to be aligned with the latest version the Streams API.

Note

This is a note on error handling.

When using promises rejection reasons should always be instances of the ECMAScript Error type such as DOMException or the built in ECMAScript error types. See Promise rejection reasons. In the TCP and UDP Socket API the error names defined in WebIDL Exceptions are used. If additional error names are needed an update to Github WebIDL should be requested through a Pull Request.

Note

This is a note on data types of TCP and UDP to send and receive.

In the previous version of this API the send() method accepted the following data types for the data to send: DOMString,Blob, ArrayBuffer or ArrayBufferView. This was aligned with the send() method for Web Sockets. In this Streams API based version only ArrayBuffer is accepted as type for data to send. The reason is that encoding issues in a Streams based API should instead be handled by a transform stream.

This document was published by the System Applications Working Group as a Working Group Note. If you wish to make comments regarding this document, please send them to public-sysapps@w3.org (subscribe, archives). All comments are welcome.

W3C makes this document available under the terms of the W3C Software and Document License pursuant to W3C's policy for Relicensing Unfinished W3C Specifications. Publication as a Working Group Note does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 1 August 2014 W3C Process Document.

Table of Contents

1. Introduction

This section is non-normative.

Use this API to send and receive data over the network using TCP or UDP.

Examples of use cases for this API are:

2. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key word MUST is to be interpreted as described in [RFC2119].

This specification defines conformance criteria that apply to a single product: the user agent that implements the interfaces that it contains.

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], as this specification uses that specification and terminology.

3. Terminology

The term webapp refers to a Web application, i.e. an application implemented using Web technologies, and executing within the context of a Web user agent, e.g. a Web browser or other Web runtime environment.

The Promise interface provides asynchronous access to the result of an operation that is ongoing, has yet to start, or has completed, as defined in [ES6].

4. Security and privacy considerations

This is a security and privacy sensitive API and a webapp must have permission to use the API. The manner in which permission is given or not varies depending on the type of web runtime environment in which this API is implemented and could be based on:

The UDPPermission, TCPPermission and TCPServerPermission interfaces provides a method hasPermission that retrieves the permission state for the requesting webapp and a method requestPermission that requests permission for the webapp to use the socket interface. If a webapp calls the contructor of a socket interface for which it has not permission to access the user agent MUST immediately throw DOMException "SecurityError".

Note

The idea behind the UDPPermission, TCPPermission and TCPServerPermission interfaces is to isolate the permission system from the socket interfaces specifications. The manner in which permission to use this API differs depending on the type of web runtime it is implemented in. For example, a web runtime for secure installed web applications may be able to open up this API so that no explicit user content is needed, while an implementation in a web browser may use a combination of web security mechanisms, such as secure transport (https:), content security policies (CSP) and a signed manifest, and user consent to open up the API.

The Permissions API, which currently is an unofficial draft, is an API that allows a web application to be aware of the status of a given permission, to know whether it is granted, denied or if the user will be asked whether the permission should be granted or not. If this API gets consensus and becomes a W3C standard, and also is extended to support permission requests, it may be possible to replace the hasPermission and requestPermission methods in this specification with a reference to the Permission API.

W3C has activities on security for web applications, see Web Application Security Working Group and on trust and permissions, see Workshop on trust and permissions for Web applications 3–4 September 2014, Paris, France and Trust & Permissions Community Group.

The CSP directive connect-src is used to restrict the allowed connection targets for XHR, Web Sockets and Server-Sent Events. It should be considered if connect-src should be extended to support allowed remote peers for raw TCP and UDP sockets as well. However, currently the allowed connection targets for connect-src are defined as a Source List and this assumes URI schemes. So, schemes for UDP and TCP, i.e. udp: and tcp:, might have to be defined. See address + port vs uri.

6. UDPPermission Interface

This interface exposes methods related to the permission to access the UDPSocket interface. Permission could be given based on user consent, based on trust for the webapp, e.g. related to the origin of it and verified through web security mechanisms such as secure transport and signatures, based on previously granted or denied permission explicitly for this webapp or a combination of these mechanisms.

interface UDPPermission {
    Promise<TCPUDPPermissionState> hasPermission (optional UDPPermissionOptions udpPermissionOptions);
    Promise<void>                  requestPermission (optional UDPPermissionOptions udpPermissionOptions);
};

6.1 Methods

hasPermission
Retrieves the permission state (TCPUDPPermissionState) of the requesting webapp for creating a UDPSocket object. The method returns a Promise, which is resolved with the permission state as argument.

This method MUST run the following steps asynchronously:

  1. Create a new Promise, udpPermissionPromise, return it and run the remaining steps asynchronously.
  2. Retrieve the permission state of the requesting webapp for creating a UDPSocket object according to the udpPermissionOptions argument.
  3. If there is an error, reject udpPermissionPromise with no arguments and abort the remaining steps.
  4. When the request has been completed, resolve udpPermissionPromise with TCPUDPPermissionState providing the permission state.

ParameterTypeNullableOptionalDescription
udpPermissionOptionsUDPPermissionOptions Options for the permission state request. If this argument is omitted this is interpreted as described for UDPPermissionOptions when all dictionary fields are ommitted.
Return type: Promise<TCPUDPPermissionState>
requestPermission
Requests permission to create a UDPSocket object. The method returns a Promise, which is resolved if permission was given and rejected if permission was denied.

This method MUST run the following steps asynchronously:

  1. Create a new Promise, udpRequestPermissionPromise, return it and run the remaining steps asynchronously.
  2. If the requesting webapp is denied to create a UDPSocket object that sends UDP packets to the requested remote address and port reject tcpRequestPermissionPromise with DOMException "SecurityError" and abort the remaining steps.
  3. If the requesting webapp is denied to create a UDPSocket object that binds to the requested local address and port reject tcpRequestPermissionPromise with DOMException "SecurityError" and abort the remaining steps.
  4. If the requesting webapp is allowed to create a UDPSocket object without user interaction, e.g. based on a prearranged trust relationship or the user has already granted permission explicitly for this webapp, resolve udpRequestPermissionPromise and abort the remaining steps.
  5. Request user consent to create a UDPSocket object.
  6. If permission was granted, resolve udpRequestPermissionPromise and abort the remaining steps.
  7. If permission was not granted, reject udpRequestPermissionPromise with DOMException "SecurityError".

ParameterTypeNullableOptionalDescription
udpPermissionOptionsUDPPermissionOptions Options for the permission request. If this argument is omitted this is interpreted as described for UDPPermissionOptions when all dictionary fields are ommitted.
Return type: Promise<void>

7. TCPPermission Interface

This interface exposes methods related to the permission to access the TCPSocket interface. Permission could be given based on user consent, based on trust for the webapp, e.g. related to the origin of it and verified through web security mechanisms such as secure transport and signatures, based on previously granted or denied permission explicitly for this webapp or a combination of these mechanisms.

interface TCPPermission {
    Promise<TCPUDPPermissionState> hasPermission (optional TCPPermissionOptions tcpPermissionOptions);
    Promise<void>                  requestPermission (optional TCPPermissionOptions tcpPermissionOptions);
};

7.1 Methods

hasPermission
Retrieves the permission state (TCPUDPPermissionState) of the requesting webapp for creating a TCPSocket object. The method returns a Promise, which is resolved with the permission state as argument.

This method MUST run the following steps asynchronously:

  1. Create a new Promise, tcpPermissionPromise, return it and run the remaining steps asynchronously.
  2. Retrieve the permission state of the requesting webapp for creating a TCPSocket object that connects to the requested remote address and port.
  3. If there is an error, reject tcpPermissionPromise with no arguments and abort the remaining steps.
  4. When the request has been completed, resolve tcpPermissionPromise with TCPUDPPermissionState providing the permission state.

ParameterTypeNullableOptionalDescription
tcpPermissionOptionsTCPPermissionOptions Options for the permission state request. If this argument is omitted this is interpreted as described for TCPPermissionOptions when all dictionary fields are ommitted.
Return type: Promise<TCPUDPPermissionState>
requestPermission
Requests permission to create a TCPSocket object that creates a connection to the requested remoteAddress and remotePort. The method returns a Promise, which is resolved if permission was given and rejected if permission was denied.

This method MUST run the following steps asynchronously:

  1. Create a new Promise, tcpRequestPermissionPromise, return it and run the remaining steps asynchronously.
  2. If the requesting webapp is denied to create a TCPSocket object that connects to the requested remote address and port reject tcpRequestPermissionPromise with DOMException "SecurityError" and abort the remaining steps.
  3. If the requesting webapp is allowed to create a TCPSocket object that connects to the requested remote address and port without user interaction, e.g. based on a prearranged trust relationship or the user has already granted permission explicitly for this webapp, resolve tcpRequestPermissionPromise and abort the remaining steps.
  4. Request user consent to create a TCPSocket object that connects to the requested remote address and port.
  5. If permission was granted, resolve tcpRequestPermissionPromise and abort the remaining steps.
  6. If permission was not granted, reject tcpRequestPermissionPromise with DOMException "SecurityError".

ParameterTypeNullableOptionalDescription
tcpPermissionOptionsTCPPermissionOptions Options for the permission request. If this argument is omitted this is interpreted as described for TCPPermissionOptions when all dictionary fields are ommitted.
Return type: Promise<void>

8. TCPServerPermission Interface

This interface exposes methods related to the permission to access the TCPServerSocket interface. Permission could be given based on user consent, based on trust for the webapp, e.g. related to the origin of it and verified through web security mechanisms such as secure transport and signatures, based on previously granted or denied permission explicitly for this webapp or a combination of these mechanisms.

interface TCPServerPermission {
    Promise<TCPUDPPermissionState> hasPermission (optional TCPServerPermissionOptions tcpServerPermissionOptions);
    Promise<void>                  requestPermission (optional TCPServerPermissionOptions tcpServerPermissionOptions);
};

8.1 Methods

hasPermission
Retrieves the permission state (TCPUDPPermissionState) of the requesting webapp for creating a TCPServerSocket object. The method returns a Promise, which is resolved with the permission state as argument.

This method MUST run the following steps asynchronously:

  1. Create a new Promise, tcpServerPermissionPromise, return it and run the remaining steps asynchronously.
  2. Retrieve the permission state of the requesting webapp for creating a TCPServerSocket object according to the tcpServerPermissionOptions argument.
  3. If there is an error, reject tcpServerPermissionPromise with no arguments and abort the remaining steps.
  4. When the request has been completed, resolve tcpServerPermissionPromise with TCPUDPPermissionState providing the permission state.

ParameterTypeNullableOptionalDescription
tcpServerPermissionOptionsTCPServerPermissionOptions Options for the permission state request. If this argument is omitted this is interpreted as described for TCPServerPermissionOptions when all dictionary fields are omitted.
Return type: Promise<TCPUDPPermissionState>
requestPermission
Requests permission to create a TCPServerSocket object. The method returns a Promise, which is resolved if permission was given and rejected if permission was denied.

This method MUST run the following steps asynchronously:

  1. Create a new Promise, tcpServerRequestPermissionPromise, return it and run the remaining steps asynchronously.
  2. If the requesting webapp is denied to create a TCPServerSocket object that binds to the requested local address and port reject tcpServerRequestPermissionPromise with DOMException "SecurityError" and abort the remaining steps.
  3. If the requesting webapp is allowed to create a TCPServerSocket object without user interaction, e.g. based on a prearranged trust relationship or the user has already granted permission explicitly for this webapp, resolve tcpServerRequestPermissionPromise and abort the remaining steps.
  4. Request user consent to create a TCPServerSocket object.
  5. If permission was granted, resolve tcpServerRequestPermissionPromise and abort the remaining steps.
  6. If permission was not granted, reject tcpServerRequestPermissionPromise with DOMException "SecurityError".

ParameterTypeNullableOptionalDescription
tcpServerPermissionOptionsTCPServerPermissionOptions Options for the permission request. If this argument is omitted this is interpreted as described for TCPServerPermissionOptions when all dictionary fields are ommitted.
Return type: Promise<void>

9. Interface UDPSocket

The UDPSocket interface defines attributes and methods for UDP communication

Example 1
//
// This example shows a simple implementation of UPnP-SSDP M-SEARCH
// discovery using a multicast UDPSocket
//

var address = '239.255.255.250',
    port = '1900',
    serviceType = 'upnp:rootdevice',
    rn = '\r\n',
    search = '';

//  Request permission to send multicast messages to the address and
//  port reserved for SSDP
navigator.udpPermission.requestPermission({remoteAddress:"239.255.255.250",
                                           remotePort:1900}).then(
  () => {
    // Permission was granted

    //  Create a new UDP client socket
    var mySocket = new UDPSocket();

    // Build an SSDP M-SEARCH multicast message
    search += 'M-SEARCH * HTTP/1.1' + rn;
    search += 'ST: ' + serviceType + rn;
    search += 'MAN: "ssdp:discover"' + rn;
    search += 'HOST: ' + address + ':' + port + rn;
    search += 'MX: 10';


    // Receive and log SSDP M-SEARCH response messages
    function receiveMSearchResponses() {
      mySocket.readable.getReader().read().then(({ value, done }) => {
        if (done) return;

        console.log('Remote address: ' + value.remoteAddress +
                    'Remote port: ' + value.remotePort +
                    'Message: ' + ab2str(value.data));
        // ArrayBuffer to string conversion could also be done by piping
        // through a transform stream. To be updated when the Streams API
        // specification has been stabilized on this point.
      });
    }

    // Join SSDP multicast group
    mySocket.joinMulticast(address);

    // Send SSDP M-SEARCH multicast message
    mySocket.writeable.write(
      {data : str2ab(search),
       remoteAddress : address,
       remotePort : port
      }).then(
        () => {
          // Data sent sucessfully, wait for response
          console.log('M-SEARCH Sent');
          receiveMSearchResponses();
        },
        e => console.error("Sending error: ", e);
    );

    // Log result of UDP socket setup.
    mySocket.opened.then(
      () => {
        console.log("UDP socket created sucessfully");
      },
      e =>console.error("UDP socket setup failed due to error: ", e);
    );

    // Handle UDP socket closed, either as a result of the application
    // calling mySocket.close() or an error causing the socket to be
    // closed.
    mySocket.closed.then(
      () => {
         console.log("Socket has been cleanly closed");
      },
      e => console.error("Socket closed due to error: ", e);
    );

  },
  e => console.error("Sending SSDP multicast messages was denied due
                      to error: ", e);
);
[Constructor (optional UDPOptions options)]
interface UDPSocket {
    readonly    attribute DOMString?       localAddress;
    readonly    attribute unsigned short?  localPort;
    readonly    attribute DOMString?       remoteAddress;
    readonly    attribute unsigned short?  remotePort;
    readonly    attribute boolean          addressReuse;
    readonly    attribute boolean          loopback;
    readonly    attribute SocketReadyState readyState;
    readonly    attribute Promise          opened;
    readonly    attribute Promise          closed;
    readonly    attribute ReadableStream   readable;
    readonly    attribute WriteableStream  writeable;
    Promise close ();
    void    joinMulticast (DOMString multicastGroupAddress);
    void    leaveMulticast (DOMString multicastGroupAddress);
};

9.1 Attributes

addressReuse of type boolean, readonly
true allows the socket to be bound to a local address/port pair that already is in use. Can be set by the options argument in the constructor. Default is true.
closed of type Promise, readonly
Detects when the UDP socket has been closed, either cleanly by the webapp calling close()) or through an error situation, e.g. network contact lost. Returns the closedPromise that was created in the UDPSocket constructor.
localAddress of type DOMString, readonly , nullable
The IPv4/6 address of the local interface, e.g. wifi or 3G, that the UDPSocket object is bound to. Can be set by the constructor's options argument's localAddress member. If this member is not present but the remoteAddress member is present, the user agent binds the socket to a local IPv4/6 address based on the routing table and possiby a preselect default local interface to use for the selected remoteAddress. Else, i.e. neither the localAddress or the remoteAddress members are present in the constructor's options argument, the localAddress attribute is set to null.
localPort of type unsigned short, readonly , nullable
The local port that the UDPSocket object is bound to. Can be set by the options argument in the constructor. If not set the user agent binds the socket to an ephemeral local port decided by the system and this attribute is null.
loopback of type boolean, readonly
Only applicable for multicast. true means that sent multicast data is looped back to the sender. Can be set by the options argument in the constructor. Default is false.
opened of type Promise, readonly
Detects the result of the UDP socket creation attempt. Returns the openedPromise that was created in the UDPSocket constructor.
readable of type ReadableStream, readonly
The object that represents the UDP socket's source of data, from which you can read. [STREAMS]
readyState of type SocketReadyState, readonly
The state of the UDP Socket object. A UDP Socket object can be in "open" "opening" or "closed" states. See enum SocketReadyState for details.
remoteAddress of type DOMString, readonly , nullable
The default remote host name or IPv4/6 address that is used for subsequent send() calls. Null if not stated by the options argument of the constructor.
remotePort of type unsigned short, readonly , nullable
The default remote port that is used for subsequent send() calls. Null if not stated by the options argument of the constructor
writeable of type WriteableStream, readonly
The object that represents the UDP socket's destination for data, into which you can write. [STREAMS]

9.2 Methods

close

Closes the UDP socket. Returns the closedPromise that was created in the UDPSocket constructor.

No parameters.
Return type: Promise
joinMulticast

Joins a multicast group identified by the given address.

Note that even if the socket is only sending to a multicast address, it is a good practice to explicitely join the multicast group (otherwise some routers may not relay packets).

ParameterTypeNullableOptionalDescription
multicastGroupAddressDOMString The multicast group address.
Return type: void
leaveMulticast

Leaves a multicast group membership identified by the given address.

ParameterTypeNullableOptionalDescription
multicastGroupAddressDOMString The multicast group address.
Return type: void

When the UDPSocket constructor is invoked, the user agent MUST run the following steps:

  1. Create a new UDPSocket object ("mySocket").
  2. If the webapp does not have permission to create a UDPSocket object according to the options argument then throw DOMException "SecurityError" and abort the remaining steps.
  3. If the options argument's remoteAddress member is present and it is a valid host name or IPv4/6 address then set the mySocket.remoteAddress attribute (default remote address) to the requested address. Else, if the remoteAddress member is present but it is not a valid host name or IPv4/6 address then throw DOMException InvalidAccessError and abort the remaining steps. Otherwise, if the options argument's remoteAddress member is absent then set the mySocket.remoteAddress attribute (default remote address) to null.
  4. If the options argument's remotePort member is present and it is a valid port number then set the mySocket.remotePort attribute (default remote port) to the requested port. Else, if the remotePort member is present but it is not a valid port number then throw DOMException InvalidAccessError and abort the remaining steps. Otherwise, if the options argument's remotePort member is absent then set the mySocket.remotePort attribute (default port number) to null.
  5. If the options argument's localAddress member is present and the options argument's remoteAddress member is present, execute the following step:
    • If the options argument's localAddress member is a valid IPv4/6 address for a local interface that can be used to connect to the selected remoteAddress (according to the routing table) bind the socket to this local IPv4/6 address and set the mySocket.localAddress attribute to this addres. Else, if the localAddress member is present but it is not a valid local IPv4/6 address for a local interface that can be used to connect to the selected remoteAddress, throw DOMException InvalidAccessError and abort the remaining steps.
    Else, if the options argument's localAddress member is present and the options argument's remoteAddress member is absent, execute the following step:
    • If the options argument's localAddress member is a valid IPv4/6 address for a local interface on the device bind the socket to this local IPv4/6 address and set the mySocket.localAddress attribute to this addres. Else, if the localAddress member is present but it is not a valid local IPv4/6 address for a local interface on the device, throw DOMException InvalidAccessError and abort the remaining steps. Note that binding the UDPSocket to a certain local interface means that the socket can only be used to send UDP datagrams to peers reachable through this local interface.
    Else, if the options argument's localAddress member is absent, and the options argument's remoteAddress member is present, execute the following steps:
    1. Use the routing table to determine the local interface(s) that can be used to send datagrams to the selected remoteAddress. If no local interface can be used to send datagrams to the selected remoteAddress, throw DOMException InvalidAccessError and abort the remaining steps.
    2. If the routing table states that more than one local interface can be used to send datagrams to the selected remoteAddress bind the socket to the IPv4/6 address of the "default" local interface to use for the selected remoteAddress. The selection of a "default" local interface is out of scope for this specification.
    3. Set the mySocket.localAddress attribute to the local address that the socket is bound to.
    Else, i.e. the options argument's localAddress member is absent, and the options argument's remoteAddress member is absent, execute the following step:
    • Set the mySocket.localAddress attribute to null.
  6. If the options argument's localPort member is absent then bind the socket to an ephemeral local port decided by the system and set the mySocket.localPort attribute to null. Otherwise, bind the socket to the requested local port and set the mySocket.localPort attribute to the local port that the socket is bound to.
  7. Set the mySocket.addressReuse attribute to the value of the options argument's addressReuse member if it is present or to true if the options argument's addressReuse member is not present.
  8. If the options argument's loopback member is present then set the mySocket.loopback attribute to the value of this field. Else set this attribute to false.
  9. Set the mySocket.readyState attribute to "opening".
  10. Create a new promise, "openedPromise", and store it so it can later be returned by the opened property.
  11. Create a new promise, "closedPromise", and store it so it can later be returned by the closed property and the close method.
  12. Let the mySocket.readable attribute be a new ReadableStream object, [STREAMS]. The user agent MUST implement the adaptation layer to [STREAMS] for this new ReadableStream object through implementation of a number of functions that are given as input arguments to the constructor and called by the [STREAMS] implementation. The semantics for these functions are described below:
    • The constructor's start() function is called immediately by the [STREAMS] implementation. The start() function MUST run the following steps:
      1. Setup the UDP socket to the bound local and remote address/port pairs in the background (without blocking scripts) and return openedPromise.
      2. When the UDP socket has been successfully setup the following steps MUST run:
        1. Change the mySocket.readyState attribute's value to "open".
        2. Resolve openedPromise with undefined.
      The following internal methods of the ReadableStream are arguments of the constructor's start() function and MUST be called by the start() function implementation according to the following steps:
      • The enqueue() argument of start() is a function that pushes received data into the internal buffer.
        When a new UDP datagram has been received the following steps MUST run:
        1. Create a new instance of UDPMessage.
        2. Set the UDPMessage object's data member to a new read-only ArrayBuffer object whose contents are the received UDP datagram [TYPED-ARRAYS].
        3. Set the remoteAddress member of the UDPMessage object to the source address of the received UDP datagram.
        4. Set the remotePort member of the UDPMessage object to the source port of the received UDP datagram.
        5. Call enqueue() to push the UDPMessage object into the internal [STREAMS] receive buffer. Note that enqueue() returns false if the high watermark of the buffer is reached. However, as there is no flow control mechanism in UDP the flow of datagrams can't be stopped. The enqueue() return value should therefore be ignored. This means that datagrams will be lost if the internal receive buffer has been filled to it's memory limit but this is the nature of an unreliable protocol as UDP.
      • The error() argument of start() is a function that handles readable stream errors and closes the readble stream.
        Upon detection that the attempt to setup a new UDP socket (mySocket.readyState is "opening") has failed, e.g. because the local address/port pair is already in use and mySocket.addressReuse is false, the following steps MUST run:
        1. Call error() with DOMException "NetworkError".
        2. Reject openedPromise with DOMException "NetworkError".
        3. Reject closedPromise with DOMException "NetworkError".
        4. Change the mySocket.readyState attribute's value to "closed" and release any underlying resources associated with this socket.
        Upon detection that there is an error with the established UDP socket (mySocket.readyState is "open"), e.g. network connection is lost, the following steps MUST run:
        1. Call error() with DOMException "NetworkError".
        2. Reject closedPromise with DOMException "NetworkError".
        3. Change the mySocket.readyState attribute's value to "closed" and release any underlying resources associated with this socket.
        When a new UDP datagram has been received and upon detction that it is not possible to convert the received UDP data to ArrayBuffer, [TYPED-ARRAYS], the following steps MUST run:
        1. Call error() with TypeError.
        2. Reject closedPromise with TypeError.
        3. Change the mySocket.readyState attribute's value to "closed" and release any underlying resources associated with this socket.
    • The constructor's pull() function MUST be omitted as there is no flow control mechanism in UDP and the flow of datagrams cannot be stopped and started again.
    • The constructor's cancel() function input argument is called by the [STREAMS] implementation when the ReadbleStream should be canceled. For UDP this means that the UDP socket should be closed for reading and writing. The cancel() function MUST run the following steps:
      1. If mySocket.readyState is "closed" then do nothing and abort the remaning steps.
      2. If mySocket.readyState is "opening" then fail the UDP socket setup process, reject openedPromise with DOMException AbortError and set the mySocket.readyState attribute to "closed".
      3. If mySocket.readyState is "open" the the following steps MUST run:
        1. Call mySocket.writeable.close() to assure that any buffered send data is sent.
        2. Set the mySocket.readyState attribute's value to "closed".
        3. Resolve closedPromise with undefined and release any underlying resources associated with this socket.
      Issue 1

      If the constructor's strategy argument is omitted the default backpressure behavior of readable streams applies. Currently this means that the ReadableStream object begins applying backpressure after 1 chunk has been enqueued to the internal ReadableStream object's input buffer. To be further investigated which readable stream strategy that should be applied to UDP.

  13. Let the mySocket.writeable attribute be a new WritableStream object, [STREAMS]. The user agent MUST implement the adaptation layer to [STREAMS] for this new WritableStream object through implementation of a number of functions that are given as input arguments to the constructor and called by the [STREAMS] implementation. The semantics for these functions are described below:
    • The constructor's start() function MUST run the following steps:
      1. Create a new promise, "writableStartPromise".
      2. If the attempt to create a new UDP socket (see the description of the semantics for the mySocket.readable attribute constructor's start() function ) succeded resolve writableStartPromise with undefined, else reject writableStartPromise with DOMException "NetworkError".
    • The constructor's write(chunk) function is called by the [STREAMS] implementation to write UDP data. The write() function MUST run the following steps:
      1. Create a new promise, "writePromise"
      2. Convert the chunk argument to a UDPMessage object (per [WEBIDL] dictionary conversion).
      3. If no default remote address was specified in the UDPSocket's constructor options argument's remoteAddress member and the UDPMessage object's remoteAddress member is not present or null then throw DOMException InvalidAccessError and abort these steps.
      4. If no default remote port was specified in the UDPSocket's constructor options argument's remotePort member and the UDPMessage object's remotePort member is not present or null then throw DOMException InvalidAccessError and abort these steps.
      5. If the UDPMesssage object's remoteAddress and/or remotePort member(s) are present but the webapp does not have permission to send UDP packets to this address and port then throw DOMException SecurityError and abort these steps.
      6. Send UDP data with data passed in the data member of the UDPMessage object. The destination address is the address defined by the UDPMesssage object's remoteAddress member if present, else the destination address is defined by the UDPSocket's constructor options argument's remoteAddress member. The destination port is the port defined by the UDPMesssage object's remotePort member if present, else the destination port is defined by the UDPSocket's constructor options argument's remotePort member.
      7. If sending succeed resolve writePromise with undefined, else reject writePromise with DOMException "NetworkError".
    • The constructor's close() and abort() functions MUST be omitted as it is not possible to just close the writable side of a UDP socket.
      Issue 2

      If the constructor's strategy argument is omitted the Default strategy for Writable Streams applies. Currently this means that the WriteableStream object goes to "waiting" state after 1 chunk has been written to the internal WriteableStream object's output buffer. This means that the webapp should use .ready to be notified of when the state changes to "writable", i.e. the queued chunk has been written to the remote peer and more data chunks could be written. To be further investigated which WritableStreamStrategy that should be applied to UDP.

  14. Return the newly created UDPSocket object ("mySocket") to the webapp.

The close method when invoked MUST run the following steps:

  1. Call mysocket.readable.cancel(reason). (Reason codes TBD.)
  2. Return closedPromise.

10. Interface TCPSocket

The TCPSocket interface defines attributes and methods for TCP communication

Example 2
//
// This example shows a simple TCP echo client.
// The client will send "Hello World" to the server on port 6789 and log
// what has been received from the server.
//

//  Request permission to connect to server at address 127.0.0.1 on port
//  6789

navigator.tcpPermission.requestPermission({remoteAddress:"127.0.0.1", remotePort:6789}).then(
  () => {
    // Permission was granted
    // Create a new TCP client socket and connect to remote host
    var mySocket = new TCPSocket("127.0.0.1", 6789);

    // Send data to server
    mySocket.writeable.write("Hello World").then(
        () => {

            // Data sent sucessfully, wait for response
            console.log("Data has been sent to server");
            mySocket.readable.getReader().read().then(
                ({ value, done }) => {
                    if (!done) {
                        // Response received, log it:
                        console.log("Data received from server:" + value);
                    }

                    // Close the TCP connection
                    mySocket.close();
                }
            );
        },
        e => console.error("Sending error: ", e);
    );

    // Signal that we won't be writing any more and can close the write half of the connection.
    mySocket.halfClose();

    // Log result of TCP connection attempt.
    mySocket.opened.then(
      () => {
        console.log("TCP connection established sucessfully");
      },
      e =>console.error("TCP connection setup failed due to error: ", e);
    );

    // Handle TCP connection closed, either as a result of the webapp
    // calling mySocket.close() or the other side closed the TCP
    // connection or an error causing the TCP connection to be closed.
    mySocket.closed.then(
      () => {
         console.log("TCP socket has been cleanly closed");
      },
      e => console.error("TCP socket closed due to error: ", e);
    );
  },
  e => console.error("Connection to 127.0.0.1 on port 6789 was denied
                     due to error: ", e);
);
[Constructor (DOMString remoteAddress, unsigned short remotePort,
                 optional TCPOptions options)]
interface TCPSocket {
    readonly    attribute DOMString        remoteAddress;
    readonly    attribute unsigned short   remotePort;
    readonly    attribute DOMString        localAddress;
    readonly    attribute unsigned short   localPort;
    readonly    attribute boolean          addressReuse;
    readonly    attribute boolean          noDelay;
    readonly    attribute SocketReadyState readyState;
    readonly    attribute Promise          opened;
    readonly    attribute Promise          closed;
    readonly    attribute ReadableStream   readable;
    readonly    attribute WriteableStream  writeable;
    Promise close ();
    void    halfClose ();
};

10.1 Attributes

addressReuse of type boolean, readonly
true allows the socket to be bound to a local address/port pair that already is in use. Can be set by the options argument in the constructor. Default is true.
closed of type Promise, readonly
Detects when the TCP connection has been closed, either cleanly (initiated either by the server, or by the client webapp calling close()) or through an error situation. Returns the closedPromise that was created in the TCPSocket constructor.
localAddress of type DOMString, readonly
The IPv4/6 address of the local interface, e.g. wifi or 3G, that the TCPSocket object is bound to. Can be set by the options argument in the constructor. If not set the user agent binds the socket to an IPv4/6 address based on the routing table and possibly a preselect default local interface to use for the selected remoteAddress.
localPort of type unsigned short, readonly
The local port that the TCPSocket object is bound to. Can be set by the options argument in the constructor. If not set the user agent binds the socket to an ephemeral local port decided by the system.
noDelay of type boolean, readonly
true if the Nagle algorithm for send coalescing, [NAGLE], is disabled. Can be set by the options argument in the constructor. Default is true.
opened of type Promise, readonly
Detects the result of the TCP connection attempt with the remote peer. Returns the openedPromise that was created in the TCPSocket constructor.
readable of type ReadableStream, readonly
The object that represents the TCP socket's source of data, from which you can read. [STREAMS]
readyState of type SocketReadyState, readonly
The state of the TCP Socket object. See enum SocketReadyState for details.
remoteAddress of type DOMString, readonly
The host name or IPv4/6 address of the peer as stated by the remoteAddress argument in the constructor.
remotePort of type unsigned short, readonly
The port of the peer as stated by the remotePort argument in the constructor.
writeable of type WriteableStream, readonly
The object that represents the TCP socket's destination for data, into which you can write. [STREAMS]

10.2 Methods

close

Closes the TCP socket. Returns the closedPromise that was created in the TCPSocket constructor.

No parameters.
Return type: Promise
halfClose

Half closes the TCP socket.

No parameters.
Return type: void

When the TCPSocket constructor is invoked, the user agent MUST run the following steps:

  1. Create a new TCPSocket object ("mySocket").
  2. If the webapp does not have permission to create a TCPSocket object that connects to the remoteAddress/remotePort as stated by the input arguments, then throw DOMException "SecurityError" and abort the remaining steps.
  3. If the remoteAddress argument is not a valid host name or IPv4/6 address and/or the remotePort argument is not a valid port number then throw DOMException "InvalidAccessError" and abort the remaining steps, else set the mySocket.remoteAddress and mySocket.remotePort attributes to the requested values.
  4. If the options argument's localAddress member is present and it is a valid IPv4/6 address for a local interface that can be used to connect to the selected remoteAddress (according to the routing table) bind the socket to this local IPv4/6 address and set the mySocket.localAddress attribute to this addres. Else, if the localAddress member is present but it is not a valid local IPv4/6 address for a local interface that can be used to connect to the selected remoteAddress then throw DOMException "InvalidAccessError" and abort the remaining steps.
    Otherwise, if the options argument's localAddress member is absent, execute the following steps:
    1. Use the routing table to determine the local interface(s) that can be used to connect to the selected remoteAddress. If no local interface can be used to connect to the selected remoteAddress then throw DOMException "InvalidAccessError" and abort the remaining steps.
    2. If the routing table states that more than one local interface can be used to connect to the selected remoteAddress bind the socket to the IPv4/6 address of the "default" local interface to use for the selected remoteAddress. The selection of a "default" local interface is out of scope for this specification.
    3. Set the mySocket.localAddress attribute to the local address that the socket is bound to.
  5. If the options argument's localPort member is absent then bind the socket to an ephemeral local port decided by the system and set the mySocket.localPort attribute to this port. Otherwise, bind the socket to the requested local port and set the mySocket.localPort attribute to the local port that the socket is bound to.
  6. Set the mySocket.addressReuse attribute to the value of the options argument's addressReuse member if it is present or to true if the options argument's addressReuse member is not present.
  7. Set the mySocket.noDelay attribute to the value of the options argument's noDelay member if it is present or to true if the options argument's noDelay member is not present.
  8. Set the mySocket.readyState attribute to "opening".
  9. Create a new promise, "openedPromise", and store it so it can later be returned by the opened property.
  10. Create a new promise, "closedPromise", and store it so it can later be returned by the closed property and the close method.
  11. Let the mySocket.readable attribute be a new ReadableStream object, [STREAMS]. The user agent MUST implement the adaptation layer to [STREAMS] for this new ReadableStream object through implementation of a number of functions that are given as input arguments to the constructor and called by the [STREAMS] implementation. The semantics for these functions are described below:
    • The constructor's start() function is called immediately by the [STREAMS] implementation. The start() function MUST run the following steps:
      1. A TCP connection setup handshake to the requested address and port MUST be performed in the background (without blocking scripts). Return openedPromise.
      2. When the TCP connection has been successfully established the following steps MUST run:
        1. Change the mySocket.readyState attribute's value to "open".
        2. Resolve openedPromise with undefined.
      The following functions are arguments of the constructor's start() function and MUST be called by the start() function implementation according to the following steps:
      • The enqueue() argument of start() is a function that pushes received data into the internal buffer.
        When new TCP data is received the following steps MUST run:
        1. Create a new read-only ArrayBuffer object whose contents are the received TCP data.
        2. Call enqueue() to push the ArrayBuffer into the internal [STREAMS] receive buffer.
        3. If the high watermark of the buffer is reached enqueue() returns false and the TCP flow control MUST be used to stop the data transmission from the remote peer.
      • The close() argument of start() is a function that closes the readable stream.
        Upon detection that the TCP connection has been closed cleanly (initiated either by the server, or by the client webapp calling close()) through a successful TCP connection closing handshake the following steps MUST run:
        1. Call close().
        2. Set the mySocket.readyState attribute's value to "closed" and release any underlying resources associated with this socket.
        3. Resolve closedPromise with undefined.
      • The error() argument of start() is a function that handles readable stream errors and closes the readble stream.
        Upon detection that the attempt to create a new TCP socket and establish a new TCP connection (mySocket.readyState is "opening") has failed the following steps MUST run:
        1. Call error() with DOMException "NetworkError".
        2. Reject openedPromise with DOMException "NetworkError".
        3. Reject closedPromise with DOMException "NetworkError".
        4. Change the mySocket.readyState attribute's value to "closed" and release any underlying resources associated with this socket.
        Upon detection that the established TCP connection (mySocket.readyState is "open") has been lost the following steps MUST run:
        1. Call error() with DOMException "NetworkError".
        2. Reject closedPromise with DOMException "NetworkError".
        3. Change the mySocket.readyState attribute's value to "closed" and release any underlying resources associated with this socket.
        Upon detection that the TCP connection closing handshake failed (mySocket.readyState is "closing") has failed the following steps MUST run:
        1. Call error() with DOMException "NetworkError".
        2. Reject closedPromise with DOMException "NetworkError".
        3. Change the mySocket.readyState attribute's value to "closed" and release any underlying resources associated with this socket.
        When new TCP data has been received and upon detction that it is not possible to convert the received data to ArrayBuffer, [TYPED-ARRAYS], the following steps MUST run:
        1. Call error() with TypeError.
        2. Reject closedPromise with TypeError.
        3. Change the mySocket.readyState attribute's value to "closed" and release any underlying resources associated with this socket.
    • The constructor's pull() function is called by the [STREAMS] implementation if the internal buffer has been emptied, but the stream's consumer still wants more data. The pull() function MUST run the following steps:
      1. The function MUST resume receiving TCP data through the TCP flow control mechanism.
    • The constructor's cancel() function input argument is called by the [STREAMS] implementation when the ReadbleStream should be canceled. For TCP this means that the TCP connection should be terminated. The cancel() function MUST run the following steps:
      1. If mySocket.readyState is "closing" or "closed" then do nothing and abort the remaning steps.
      2. If mySocket.readyState is "opening" then fail the connection attempt, reject openedPromise and closedPromise with DOMException AbortError and set the mySocket.readyState attribute to "closing".
      3. If mySocket.readyState is "open" then the following steps MUST run:
        1. Call mySocket.writeable.close() to assure that any buffered send data is sent before closing the socket.
        2. Set the mySocket.readyState attribute's value to "closing".
        3. Initiate TCP closing handshake.
      Issue 3

      If the constructor's strategy argument is omitted the default backpressure behavior of readable streams applies. Currently this means that the ReadableStream object begins applying backpressure after 1 chunk has been enqueued to the internal ReadableStream object's input buffer. To be further investigated which readable stream strategy that should be applied to TCP.

  12. Let the mySocket.writeable attribute be a new WritableStream object, [STREAMS]. The user agent MUST implement the adaptation layer to [STREAMS] for this new WritableStream object through implementation of a number of functions that are given as input arguments to the constructor and called by the [STREAMS] implementation. The semantics for these functions are described below:
    • The constructor's start() function MUST run the following steps:
      1. Create a new promise, "writableStartPromise".
      2. If the attempt to create a new TCP socket and establish a new TCP connection (see the description of the semantics for the mySocket.readable attribute constructor's start() function ) succeded resolve writableStartPromise with undefined, else reject writableStartPromise with DOMException "NetworkError".
    • The constructor's write(chunk) function is called by the [STREAMS] implementation to write data to the remote peer on the TCP connection. The write() function MUST run the following steps:
      1. Create a new promise, "writePromise"
      2. Send TCP data with data passed in the chunk parameter to the address and port of the recipient as stated by the TCPSocket object constructor's remoteAddress and remotePort fields. The data in the chunk parameter can be of any type.
      3. If sending succeed resolve writePromise with undefined, else reject writePromise with DOMException "NetworkError".
    • The constructor's close() function is called by the [STREAMS] implementation to close the writable side of the connection, that is a TCP "half close" is performed. The close() function MUST run the following steps:
      1. If mySocket.readyState is "closing" or "closed" then do nothing.
      2. If mySocket.readyState is "opening" then complete the connection attempt. If succesful send FIN and set the mySocket.readyState attribute to "halfclosed".
      3. If mySocket.readyState is "open" then send FIN and set the mySocket.readyState attribute to "halfclosed".
      Note that the Streams implementation will call close() after all queued-up writes successfully completed.
    • The constructor's abort() function is called by the [STREAMS] implementation to abort the writable side of the connection. This function MUST run the same steps as close() but note that the Streams implementation will throw away any pending queued up chunks.
      Issue 4

      If the constructor's strategy argument is omitted the Default strategy for Writable Streams applies. Currently this means that the WriteableStream object goes to "waiting" state after 1 chunk has been written to the internal WriteableStream object's output buffer. This means that the webapp should use .ready to be notified of when the state changes to "writable", i.e. the queued chunk has been written to the remote peer and more data chunks could be written. To be further investigated which WritableStreamStrategy that should be applied to TCP.

  13. Return the newly created TCPSocket object ("mySocket") to the webapp.

The close() method when invoked MUST run the following steps:

  1. Call mysocket.readable.cancel(reason). (Reason codes TBD.)
  2. Return closedPromise.

The halfClose() method when invoked MUST run the following steps:

  1. Call mysocket.writeable.close().

11. Interface TCPServerSocket

The TCPServerSocket interface supports TCP server sockets that listens to connection attempts from TCP clients

Example 3
//
// This example shows a simple TCP echo server.
// The server will listen on port 6789 and respond back with whatever
// has been sent to the server.
//

 //  Request permission to listen on port 6789
 navigator.tcpServerPermission.requestPermission({"localPort":6789}).then(
   () => {
     // Permission was granted

     //  Create a new server socket that listens on port 6789
     var myServerSocket = new TCPServerSocket({"localPort": 6789});

     // Listen for connection attempts from TCP clients.
     listenForConnections();
     function listenForConnections() {
       myServerSocket.listen().then(
           connectedSocket => {
           // A connection has been accepted

             console.log ("Connection accepted from address: " +
                           connectedSocket.remoteAddress + " port: " +
                           connectedSocket.remotePort);

             var reader = connectedSocket.readable.getReader();

             // Wait for data
             waitForData();
             function waitForData () {
               reader.read().then(
                 ({ value, done }) => {
                   if (done) return;

                   // Data in buffer, read it
                   console.log("Received: " + value);

                   // Send data back
                   connected.writeable.write(value).then(
                     () => console.log("Sending data succeeded"),
                     e => console.error("Failed to send: ", e);
                   });
                   // Continue to wait for data
                   waitForData ();
                 }
               );

             }

             // Continue to listen for new connections
             listenForConnections();
       },
           e => {
             console.error("A client connection attempt failed: ", e);

             // Continue to listen for new connections
             listenForConnections();
           }

       );
     }

     // Log result of TCP server socket creation attempt.
     myServerSocket.opened.then(
       () => {
         console.log("TCP server socket created sucessfully");
       },
       e =>console.error("TCP server socket creation failed due to error: ", e);
     );

     // Handle TCP server closed, either as a result of the webapp
     // calling myServerSocket.close() or due to an error.
     myServerSocket.closed.then(
       () => {
          console.log("TCP server socket has been cleanly closed");
       },
       e => console.error("TCP server socket closed due to error: ", e);
     );

   },
   e => console.error("TCP Server Socket on local port 6789 was denied
                      due to error: ", e);
 );
[Constructor (optional TCPServerOptions options)]
interface TCPServerSocket {
    readonly    attribute DOMString        localAddress;
    readonly    attribute unsigned short   localPort;
    readonly    attribute boolean          addressReuse;
    readonly    attribute SocketReadyState readyState;
    readonly    attribute Promise          opened;
    readonly    attribute Promise          closed;
    Promise listen ();
    Promise close ();
};

11.1 Attributes

addressReuse of type boolean, readonly
true allows the socket to be bound to a local address/port pair that already is in use. Can be set by the options argument in the constructor. Default is true.
closed of type Promise, readonly
Detects when the TCP server socket been closed, either cleanly by the webapp calling close()) or through an error situation. Returns the closedPromise that was created in the TCPSocket constructor.
localAddress of type DOMString, readonly
The IPv4/6 address of the interface, e.g. wifi or 3G, that the TCPServer Socket object is bound to. Can be set by the options argument in the constructor. If not set the the server will accept connections directed to any IPv4 address and this atribute is set to null.
localPort of type unsigned short, readonly
The local port that the TCPServerSocket object is bound to. Can be set by the options argument in the constructor. If not set the user agent binds the socket to an ephemeral local port decided by the system and sets this atribute to null.
opened of type Promise, readonly
Detects the result of the TCP server socket opening process when the socket is ready to receive connection attempts from clients. Returns the openedPromise that was created in the TCPServerSocket constructor.
readyState of type SocketReadyState, readonly
The state of the TCP server object. A TCP server socket object can be in "open", "opening" or "closed" states. See enum SocketReadyState for details.

11.2 Methods

close

Closes the TCP server socket. If listen() has been called the listening for incoming connections is stopped but existing TCP connections are kept open. Returns the closedPromise that was created in the TCPServerSocket constructor.

No parameters.
Return type: Promise
listen

Listens for incoming connection attempts on the specified port and address. Returns the connectionPromise, which is for a succeful connection resolved with the TCPSocket object for the accepted TCP connection and rejected with DOMException "NetworkError" if there is an error on an incoming connection attempt.

No parameters.
Return type: Promise

When the TCPServerSocket constructor is invoked, the user agent MUST run the following steps:

  1. Create a new TCPServerSocket object ("myServerSocket").
  2. If the webapp does not have permission to create a TCPServerSocket object according to the options argument then throw DOMException "SecurityError" and abort the remaining steps.
  3. If the options argument's localAddress member is absent the server will accept connections directed to any IPv4 address and the localAddress attribute is set to null. Otherwise, if the requested local address is a valid IPv4/6 address for a local interface on the device bind the server socket to this local IPv4/6 address and set the localAddress attribute to this address. Else, if the localAddress member is present but it is not a valid local IPv4/6 address for a local interface on the device, throw DOMException InvalidAccessError and abort the remaining steps.
  4. If the options argument's localPort member is absent then bind the socket to an ephemeral local port decided by the system and set the localPort attribute to null. Otherwise, bind the socket to the requested local port and set the localPort attribute to the local port that the socket is bound to.
  5. Set the addressReuse attribute to the value of the options argument's addressReuse member if it is present or to true if the options argument's addressReuse member is not present.
  6. Set the myServerSocket.readyState attribute to "opening".
  7. Create a new promise, "openedPromise", and store it so it can later be returned by the opened property.
  8. Create a new promise, "closedPromise", and store it so it can later be returned by the closed property and the close method.
  9. Return the newly created TCPServerSocket object to the webapp.

The close method when invoked MUST run the following steps:

  1. If a TCP connection setup is in progress the connection setup is finalized according to the descriptions below.
  2. Stop listening to further connection attempts from clients.
  3. Set the myServerSocket.readyState attribute to "closed".
  4. Resolve closedPromise with undefined.

The listen method when invoked MUST run the following steps:

  1. If myServerSocket.readyState attribute is"closed" then throw DOMException "InvalidStateError" and abort the remaining steps.
  2. Create a new promise, "connectionPromise".
  3. Start listening for connections on the specified local port and address. Return connectionPromise.

When a new TCP server socket has successfully been created the user agent MUST run the following steps:

  1. Change the myServerSocket.readyState attribute's value to "open".
  2. Resolve openedPromise with undefined.

When the attempt to create a new TCP server socket (myServerSocket.readyState is "opening") has failed the user agent MUST run the following steps:

  1. Change the myServerSocket.readyState attribute's value to "closed".
  2. Reject openedPromise with DOMException "NetworkError".
  3. Reject closedPromise with DOMException "NetworkError".

When there is an error on an established TCP server socket (myServerSocket.readyState is "open"), e.g. loss of network contact, the user agent MUST run the following steps:

  1. Change the myServerSocket.readyState attribute's value to "closed".
  2. Reject closedPromise with DOMException "NetworkError".

Upon a new successful connection to the TCP server socket the user agent MUST run the following steps:

  1. Let socket be a new instance of TCPSocket.
  2. Set the remoteAddress attribute of socket to the IPv4/6 address of the peer.
  3. Set the remotePort attribute of socket to the source port of the of the peer.
  4. Set the localAddress attribute of socket to the used local IPv4/6 address.
  5. Set the localPort attribute of socket to the used local source port.
  6. Set the readyState attribute of socket to "open".
  7. Set the bufferedAmount attribute of socket to 0.
  8. Resolve connectionPromise with socket as argument.

Upon a new connection attempt to the TCP server socket that can not be served, e.g. due to max number of open connections, the user agent MUST run the following steps:

  1. Reject connectionPromise with DOMException "NetworkError".

12. Dictionary UDPMessage

The UDPMessage dictionary represents UDP data including address and port of the remote peer. The field data is mandatory but remoteAddress and remotePort are optional.

dictionary UDPMessage {
             ArrayBuffer    data;
             DOMString      remoteAddress;
             unsigned short remotePort;
};

12.1 Dictionary UDPMessage Members

data of type ArrayBuffer,
Received UDP data or UDP data to send.
remoteAddress of type DOMString,
The address of the remote machine.
remotePort of type unsigned short,
The port of the remote machine.

13. Dictionary UDPOptions

States the options for the UDPSocket. An instance of this dictionary can optionally be used in the constructor of the UDPSocket object, where all fields are optional.

dictionary UDPOptions {
             DOMString      localAddress;
             unsigned short localPort;
             DOMString      remoteAddress;
             unsigned short remotePort;
             boolean        addressReuse;
             boolean        loopback;
};

13.1 Dictionary UDPOptions Members

addressReuse of type boolean,
true allows the socket to be bound to a local address/port pair that already is in use. Default is true.
localAddress of type DOMString,
The IPv4/6 address of the local interface, e.g. wifi or 3G, that the UDPSocket object is bound to. If the field is omitted, the user agent binds the socket to an IPv4/6 address based on the routing table and possibly a preselect default local interface to use for the selected remoteAddress if this member is present. Else the UDPSocket is unbound to a local interface.
localPort of type unsigned short,
The local port that the UDPSocket object is bound to. If the the field is omitted, the user agent binds the socket to a an ephemeral local port decided by the system.
loopback of type boolean,
Only applicable for multicast. true means that sent multicast data is looped back to the sender. Default is false.
remoteAddress of type DOMString,
When present the default remote host name or IPv4/6 address that is used for subsequent send() calls.
remotePort of type unsigned short,
When present the default remote port that is used for subsequent send() calls.

14. Dictionary TCPOptions

States the options for the TCPSocket. An instance of this dictionary can optionally be used in the constructor of the TCPSocket object, where all fields are optional.

dictionary TCPOptions {
             DOMString           localAddress;
             unsigned short      localPort;
             boolean             addressReuse;
             boolean             noDelay;
             boolean             useSecureTransport;
             TCPKeepAliveOptions tcpKeepAliveOptions;
             unsigned long       tcpKeepAliveSparseIntvl;
};

14.1 Dictionary TCPOptions Members

addressReuse of type boolean,
true allows the socket to be bound to a local address/port pair that already is in use. Default is true.
localAddress of type DOMString,
The IPv4/6 address of the local interface, e.g. wifi or 3G, that the TCPSocket object is bound to. If the field is omitted, the user agent binds the socket to an IPv4/6 address based on the routing table and possibly a preselect default local interface to use for the selected remoteAddress.
localPort of type unsigned short,
The local port that the TCPSocket object is bound to. If the the field is omitted, the user agent binds the socket to an ephemeral local port decided by the system.
noDelay of type boolean,
true if the Nagle algorithm for send coalescing, [NAGLE], is disabled. Default is true.
tcpKeepAliveOptions of type TCPKeepAliveOptions,
States the "keepalive" options for the TCPSocket. TCP "keepalive" causes a packet (called a 'keepalive probe') to be sent to the remote system if a long time passes with no data or acknowledgement packets received. This packet is designed to provoke an ACK response from the peer. This enables detection of a peer which has become unreachable (e.g. powered off or disconnected from the net). If this field is omitted keepalive probes will not be sent.
tcpKeepAliveSparseIntvl of type unsigned long,
The time (in seconds) between individual keepalive probes. Default is 600 seconds (10 minutes).
useSecureTransport of type boolean,
true if socket uses SSL or TLS. Default is false.
Issue 5

Use of secure transport needs more investigation

15. Dictionary TCPServerOptions

States the options for the TCPServerSocket. An instance of this dictionary can optionally be used in the constructor of the TCPServerSocket object, where all fields are optional.

dictionary TCPServerOptions {
             DOMString      localAddress;
             unsigned short localPort;
             boolean        addressReuse;
             boolean        useSecureTransport;
};

15.1 Dictionary TCPServerOptions Members

addressReuse of type boolean,
true allows the socket to be bound to a local address/port pair that already is in use. Default is true.
localAddress of type DOMString,
The IPv4/6 address of the interface, e.g. wifi or 3G, that the TCPServerSocket object is bound to. If the field is omitted, the user agent binds the server socket to the IPv4/6 address of the default local interface.
localPort of type unsigned short,
The local port that the TCPServerSocket object is bound to. If the the field is omitted, the user agent binds the socket to an ephemeral local port decided by the system.
useSecureTransport of type boolean,
true if socket uses SSL or TLS. Default is false.
Issue 6

Use of secure transport needs more investigation

16. Dictionary UDPPermissionOptions

States the options for the webapp to get status of permission for creating a UDPSocket object or to request permission to create a UDPSocket object. An instance of this dictionary can optionally be used as argument to the UDPPermission hasPermission and requestPermission methods. All fields are optional.

dictionary UDPPermissionOptions {
             DOMString      localAddress;
             unsigned short localPort;
             DOMString      remoteAddress;
             unsigned short remotePort;
};

16.1 Dictionary UDPPermissionOptions Members

localAddress of type DOMString,
The local interface that the webapp requests permission for the UDPSocket object to be bound to. If the field is omitted the webapp does not request permission to use any specific local interface, i.e. the user agent selects local interface.
localPort of type unsigned short,
The local port that the webapp requests permission for the UDPSocket object to be bound to. If the field is omitted the webapp does not request permission to use any specific local port, i.e. the user agent selects local port.
remoteAddress of type DOMString,
The host name or IPv4/6 address the webapp requests permission for the UDPSocket object to send UDP packets to. If the field is omitted it means that the webapp requests permission for the UDPSocket object to send UDP packets to any peer.
remotePort of type unsigned short,
The port of the peer the webapp requests permission for the UDPSocket object to send UDP packets to. If the field is omitted it means that the webapp requests permission for the UDPSocket object to send UDP packets to any port.

17. Dictionary TCPPermissionOptions

States the options for the webapp to get status of permission for creating a TCPSocket object or to request permission to create a TCPSocket object. An instance of this dictionary can optionally be used as argument to the TCPPermission hasPermission and requestPermission methods. All fields are optional.

dictionary TCPPermissionOptions {
             DOMString      remoteAddress;
             unsigned short remotePort;
};

17.1 Dictionary TCPPermissionOptions Members

remoteAddress of type DOMString,
The host name or IPv4/6 address the webapp requests permission for the TCPSocket object to connect to. If the field is omitted it means that the webapp requests permission for the TCPSocket object to connect to any peer.
remotePort of type unsigned short,
The port of the peer the webapp requests permission for the TCPSocket object to connect to. If the field is omitted it means that the webapp requests permission for the TCPSocket object to connect to any port.

18. Dictionary TCPServerPermissionOptions

States the options for the webapp to get status of permission for creating a TCPServerSocket object or to request permission to create a TCPServerSocket object. An instance of this dictionary can optionally be used as argument to the TCPServerPermission hasPermission and requestPermission methods. All fields are optional.

dictionary TCPServerPermissionOptions {
             DOMString      localAddress;
             unsigned short localPort;
};

18.1 Dictionary TCPServerPermissionOptions Members

localAddress of type DOMString,
The local interface that the webapp requests permission for the TCPServerSocket object to be bound to. If the field is omitted the webapp does not request permission to use any specific local interface, i.e. the user agent selects local interface.
localPort of type unsigned short,
The local port that the webapp requests permission for the TCPServerSocket object to be bound to. If the field is omitted the webapp does not request permission to use any specific local port, i.e. the user agent selects local port.

19. Enums

19.1 TCPUDPPermissionState

enum TCPUDPPermissionState {
    "granted",
    "denied",
    "prompt"
};
Enumeration description
grantedThe webapp has permission to use the requested interface.
deniedThe webapp has been denied permission to use the requested interface.
promptThe webapp needs to request permission to use the requested interface by calling requestPermission.

19.2 SocketReadyState

enum SocketReadyState {
    "opening",
    "open",
    "closing",
    "closed",
    "halfclosed"
};
Enumeration description
openingThe socket is in opening state, i.e. availability of local address/port is being checked, network status is being checked, etc. For TCP a connection with a remote peer has not yet been established.
openThe socket is ready to use to send and received data. For TCP a connection with a remote peer has been established.
closingOnly used for TCP sockets. The TCP connection is going through the closing handshake, or the close() method has been invoked.
closedThe socket is closed and can not be use to send and received data. For TCP the connection has been closed or could not be opened.
halfclosedOnly used for TCP sockets. The TCP connection has been "halfclosed" by the webapp, which means that it is not possible to send data but it is still possible to receive.

19.3 TCPKeepAliveOptions

enum TCPKeepAliveOptions {
    "off",
    "frequent-then-sparse",
    "sparse"
};
Enumeration description
offDon't use TCP keep-alives. This is the defult.
frequent-then-sparseKeep-alive probes every 10s for first minute, then send with "tcpKeepAliveSparseIntvl" after that.
sparseKeep-alive probe sent with "tcpKeepAliveSparseIntvl".

A. Acknowledgements

Many thanks to Domenic Denicola, Marcos Caceres, Jonas Sicking, Ke-Fong Lin and Alexandre Morgaut for reviewing the specification and providing very valuable feedback. Also thanks to Sony colleagues Anders Edenbrandt, Anders Isberg and Björn Isaksson for sharing their experience on socket APIs and providing support.

B. References

B.1 Normative references

[ES6]
ECMA-262, 6th Edition / Draft January 20, 2014. Draft. URL: http://people.mozilla.org/~jorendorff/es6-draft.html
[NAGLE]
John Nagle. Nagle algorithm. Request For Comments. URL: http://www.rfc-editor.org/rfc/rfc896.txt
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[STREAMS]
Domenic Denicola. Streams API. Living standard. URL: https://streams.spec.whatwg.org/
[TYPED-ARRAYS]
David Herman; Kenneth Russell. Typed Array Specification. 26 June 2013. Khronos Working Draft. URL: https://www.khronos.org/registry/typedarray/specs/latest/
[WEBIDL]
Cameron McCormack. Web IDL. 19 April 2012. W3C Candidate Recommendation. URL: http://www.w3.org/TR/WebIDL/