W3C

Network Communication API

Editors' Draft 7 March 2007

This Version:
http://dev.w3.org/cvsweb/~checkout~/2006/webapi/network-api/network-api.html
Editors:
Gorm Haug Eriksen (Opera Software ASA) <gormer@opera.com>
Charles McCathieNevile (Opera Software ASA) <chaals@opera.com>

Abstract

To enable Web applications to communicate using TCP with it's originating server this specification introduces the TCPConnection interface.

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 is a first editors' draft specification of the network API from the Web API group, part of the Rich Web Client Activity. This editor's draft does not imply any consensus of or endorsement by any member of the working group, and may contain minor or major errors. (Currently it probably contains some of both).

This document is published to solicit comments from interested parties. All comments are welcome and may be sent to public-webapi@w3.org. All messages received at this address are viewable in a public archive. This document will hopefully be published as a first W3C Working Draft in March 2007.

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.

Publication as a Working Draft 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.

Table of Contents

Introduction

The TCPConnection interface enables a TCP connection from the client to the server from which the script was downloaded and executed from. Instances of this object can be made using a constructor on the Window object.

This interface does not allow for raw access to the underlying network. For example, this interface could not be used to implement an IRC client without proxying messages through a custom server.

Add an introduction to the client-side and server-side of using the direct connection APIs. The example below could be better.

Provide an example here

  var con = null;
  try { 
    con = new TCPConnection("", "12345"); 
  }
  catch (ex) { 
    if ("SECURITY_ERR" == ex.message) { 
      alert("unable to connect") 
    } 
  }
  con.onread = function(o) { 
    if ("pong" == o.data) { alert("'success"); } 
    else { alert("unknown data"); }
  }
  con.send("ping"); 
 

The TCPConnection object

TCPConnection objects must also implement the EventTarget interface. [DOM3Events].

In [ECMAScript], an instance of TCPConnection can be created using the TCPConnection constructor. This is done by calling the TCPConnection function as part of a new expression like:

var ircConnection = new TCPConnection("example.com", "6667", true);

The TCPConnection constructor

When the TCPConnection is called as part of a new expression in ECMAScript, it returns the newly created TCPConnection object which must be initialized according to the rules below.

out TCPConnection TCPConnection(in DOMString subdomain, 
                                in DOMString port, 
                                in Boolean secure); 

The subdomain argument is prepended to the script's domain with a dot separating the two strings, and that is the target host. If null or an empty string the target host is the scripts doamin.

The port argument is the target port. The port argument must not be equal to 80, nor equal to 443, nor greater than or equal to 1024 and less than or equal to 65535. In such case an SECURITY_ERR exception must be thrown.

If the boolean secure argument is set to true, then the user agent must establish a secure connection with the target host and specified port using TLS or another protocol, negotiated with the server. [RFC2246] If this fails the user agent must act as if it had closed the connection.

Members of the TCPConnection object

interface TCPConnection {
  readonly attribute DOMString     peer;
  readonly attribute int           readyState;
           attribute EventListener onopen;
           attribute EventListener onread;
           attribute EventListener onclose;
                     void          send(in DOMString data);
                     void          disconnect();
};

The peer attribute identifies the remote host for direct (non-broadcast) connections. The peer attribute must initially be set to the empty string and must be updated once, when the connection is established, after which point it must keep the same value for the lifetime of the object.

The readyState attribute represents the state of the connection. When the object is created it must be set to 0. It can have the following values:

0 Connecting
The connection has not yet been established.
1 Connected
The connection is established and communication is possible.
2 Closed
The connection has been closed.

Once a connection is established, the readyState attribute's value must be changed to 1, and the open event must be fired on the TCPConnection object.

When data is received, the read event will be fired on the TCPConnection. Should provide an example of binary protocol. E.g. read from NTP

When the connection is closed, the readyState attribute's value must be changed to 2, and the close event must be fired on the TCPConnection object.

The onopen, onread, and onclose attributes must, when set, register their new value as an event listener for their respective events (namely open, read, close), and unregister their previous value if any.

The send(data) method transmits data using the connection. If the connection is not yet established, it must raise an INVALID_STATE_ERR exception. If the connection is established, then the behavior depends on the connection type, as described below.

The disconnect() method must close the connection, if it is open. If the connection is already closed, it must do nothing. Closing the connection causes a close event to be fired and the readyState attribute's value to change, as described above.

TCPConnection Events

All the events described in this section are events in no namespace, which do not bubble, are not cancelable, and have no default action.

The open event is fired when the connection is established. UAs must use the normal Event interface when firing this event.

The close event is fired when the connection is closed (whether by the author, calling the disconnect() method, or by the server, or by a network error). UAs must use the normal Event interface when firing this event as well.

No information regarding why the connection was closed is passed to the application in this version of this specification.

The read event is fired when when data is received for a connection. UAs must use the ConnectionReadEvent interface for this event.

interface ConnectionReadEvent : Event {
readonly attribute DOMString data;
  void initConnectionReadEvent(in DOMString typeArg, 
                                 in boolean canBubbleArg, 
                                 in boolean cancelableArg, 
                                 in DOMString dataArg);
  void initConnectionReadEventNS(in DOMString namespaceURI, 
                                   in DOMString typeArg, 
                                   in boolean canBubbleArg, 
                                   in boolean cancelableArg, 
                                   in DOMString dataArg);
};

The data attribute must contain the data that was transmitted from the peer.

The initConnectionReadEvent() and initConnectionReadEventNS() methods must initialize the event in a manner analogous to the similarly-named methods in the DOM3 Events interfaces. [DOM3EVENTS]

Events that would be fired during script execution (e.g. between the connection object being created — and thus the connection being established — and the current script completing; or, during the execution of a read event handler) must be buffered, and those events queued up and each one individually fired after the script has completed.

Initializing the TCPConnection object

When a TCPConnection object is created using this constructor, the following steps must be followed.

First, a pointer must be stored on the newly created object, called the Window pointer. This pointer must persist even if the browsing context in which the Window is located is destroyed (by removing it from a parent browsing context, for instance). The term browsing context is defined by the Window Object 1.0 specification. [Window]

Secondly, if the script's domain is not a host name (e.g. it is an IP address) then a SECURITY_ERR should be raised by the user agent. We currently don't allow connections to be set up back to an originating IP address, but we could, if the subdomain is the empty string.

Then, if the subdomain argument is null or the empty string, the target host is the script's domain. Otherwise, the subdomain argument is prepended to the script's domain with a dot separating the two strings, and that is the target host.

If either:

...then the UA must raise a SECURITY_ERR exception.

Otherwise, the user agent must verify that the the string representing the script's domain in IDNA format can be obtained without errors. If it cannot, then the user agent must raise a SECURITY_ERR exception.

The user agent may also raise a SECURITY_ERR exception at this time if, for some reason, permission to create a direct TCP connection to the relevant host is denied. Reasons could include the UA being instructed by the user to not allow direct connections, or the UA establishing (for instance using UPnP) that the network topology will cause connections on the specified port to be directed at the wrong host.

If no exceptions are raised by the previous steps, then a new TCPConnection object must be created, its peer attribute must be set to a string consisting of the name of the target host, a colon (U+003A COLON), and the port number as decimal digits.

This object must then be returned.

The user agent must then begin trying to establish a connection with the target host and specified port. (This typically would begin in the background, while the script continues to execute.)

If the secure boolean argument is set to true, then the user agent must establish a secure connection with the target host and specified port using TLS or another protocol, negotiated with the server. [RFC2246] If this fails the user agent must act as if it had closed the connection.

Once a secure connection is established, or if the secure boolean argument is not set to true, then the user agent must continue to connect to the server using the protocol described in the section entitled clients connecting over TCP. All data on connections made using TLS must be sent as "application data".

Once the connection is established, the UA must act as described in the section entitled sending and receiving data over TCP.

User agents should allow multiple TCP connections to be established per host. In particular, user agents should not apply per-host HTTP connection limits to connections established with the TCPConnection constructor.

Communication on the network

This section describes how connections are established from the client and server sides, and then describes how data is sent and received over such connections (which is the same for both clients and servers).

Clients connecting over TCP

This section defines the client-side requirements of the protocol used by the TCPConnection.

If a TCP connection to the specified target host and port cannot be established, for example because the target host is a domain name that cannot be resolved to an IP address, or because packets cannot be routed to the host, the user agent should retry creating the connection. If the user agent gives up trying to connect, the user agent must act as if it had closed the connection.

No information regarding the state of the connection is passed to the application while the connection is being established in this version of this specification.

Once a TCP/IP connection to the remote host is established, the user agent must transmit the following sequence of bytes, represented here in hexadecimal form:

0x48 0x65 0x6C 0x6C 0x6F 0x0A

This represents the string "Hello" followed by a newline, encoded in UTF-8.

The user agent must then read all the bytes sent from the remote host, up to the first 0x0A byte (inclusive). That string of bytes is then compared byte-for-byte to the following string of bytes:

0x57 0x65 0x6C 0x63 0x6F 0x6E 0x65 0x0A

This says "Welcome".

If the server sent back a string in any way different to this, then the user agent must close the connection and give up trying to connect.

Otherwise, the user agent must then take the string representing the script's domain in IDNA format, encode it as UTF-8, and send that to the remote host, followed by a 0x0A byte (a U+000A LINE FEED in UTF-8).

The user agent must then read all the bytes sent from the remote host, up to the first 0x0A byte (inclusive). That string of bytes must then be compared byte-for-byte to the string that was just sent to the server (the one with the IDNA domain name and ending with a newline character). If the server sent back a string in any way different to this, then the user agent must close the connection and give up trying to connect.

Otherwise, the connection has been established (and events and so forth get fired, as described above).

If at any point during this process the connection is closed prematurely, then the user agent must close the connection and give up trying to connect.

Servers accepting connections over TCP

This section defines the server side of the protocol described in the previous section. For authors, it should be used as a guide for how to implement servers that can communicate with Web pages over TCP.

Once a TCP/IP connection from a remote host is established, the user agent must transmit the following sequence of bytes, represented here in hexadecimal form:

0x57 0x65 0x6C 0x63 0x6F 0x6E 0x65 0x0A

This says "Welcome" and a newline in UTF-8.

The user agent must then read all the bytes sent from the remote host, up to the first 0x0A byte (inclusive). That string of bytes is then compared byte-for-byte to the following string of bytes:

0x48 0x65 0x6C 0x6C 0x6F 0x0A

"Hello" and a newline.

If the remote host sent back a string in any way different to this, then the user agent must close the connection and give up trying to connect.

Otherwise, the user agent must then take the string representing the script's domain in IDNA format, encode it as UTF-8, and send that to the remote host, followed by a 0x0A byte (a U+000A LINE FEED in UTF-8).

The user agent must then read all the bytes sent from the remote host, up to the first 0x0A byte (inclusive). That string of bytes must then be compared byte-for-byte to the string that was just sent to that host (the one with the IDNA domain name and ending with a newline character). If the remote host sent back a string in any way different to this, then the user agent must close the connection and give up trying to connect.

Otherwise, the connection has been established (and events and so forth get fired, as described above).

For author-written servers (as opposed to the server side of a peer-to-peer connection), the script's domain would be replaced by the hostname of the server. Alternatively, such servers might instead wait for the client to send its domain string, and then simply echo it back. This would allow connections from pages on any domain, instead of just pages originating from the same host. The client compares the two strings to ensure they are the same before allowing the connection to be used by author script.

If at any point during this process the connection is closed prematurely, then the user agent must close the connection and give up trying to connect.

Sending and receiving data over TCP

When the send(data) method is invoked on the connection's corresponding TCPConnection object, the user agent must take the data argument, replace any U+0000 NULL and U+0017 END OF TRANSMISSION BLOCK characters in it with U+FFFD REPLACEMENT CHARACTER characters, then transmit a U+0002 START OF TEXT character, this new data string and a single U+0017 END OF TRANSMISSION BLOCK character (in that order) to the remote host, all encoded as UTF-8.

When the user agent receives bytes on the connection, the user agent must buffer received bytes until it receives a 0x17 byte (a U+0017 END OF TRANSMISSION BLOCK character). If the first buffered byte is not a 0x02 byte (a U+0002 START OF TEXT character encoded as UTF-8) then all the data up to the 0x17 byte, inclusive, must be dropped. (This allows for future extension of this protocol.) Otherwise, all the data from (but not including) the 0x02 byte and up to (but not including) the 0x17 byte must be taken, interpreted as a UTF-8 string, and a read event must be fired on the TCPConnection object with that string as the data. If that string cannot be decoded as UTF-8 without errors, the packet should be ignored.

This protocol does not yet allow binary data (e.g. an image or video data) to be efficiently transmitted. A future version of this protocol might allow this by using the prefix character U+001F INFORMATION SEPARATOR ONE, followed by binary data which uses a particular byte (e.g. 0xFF) to encode byte 0x17 somehow (since otherwise 0x17 would be treated as transmission end by down-level UAs).

Security

Need to write this section.

If you have an unencrypted page that is (through a man-in-the-middle attack) changed, it can access a secure service that is using IP authentication and then send that data back to the attacker. Ergo we should probably stop unencrypted pages from accessing encrypted services, on the principle that the actual level of security is zero. Then again, if we do that, we prevent insecure sites from using SSL as a tunneling mechanism.

Should consider dropping the subdomain-only restriction. It doesn't seem to add anything, and prevents cross-domain chatter.

Relationship to other standards

Should have a section talking about the fact that we blithely ignoring IANA's port assignments here.

Should explain why we are not reusing HTTP for this. (HTTP is too heavy-weight for such a simple need; requiring authors to implement an HTTP server just to have a party line is too much of a barrier to entry; cannot rely on prebuilt components; having a simple protocol makes it much easier to do RAD; HTTP doesn't fit the needs and doesn't have the security model needed; etc)

References

[ECMAScript]
ECMAScript Language Specification, Third Edition. ECMA, December 1999.
[DOM3Events]
Document Object Model (DOM) Level 3 Events Specification, Björn Höhrmann, editor. World Wide Web Consortium, April 2006.
[Window]
Window Object 1.0, I. Davis, M. Stachowiak, editors. W3C, April 2006.
[RFC2046]
The TLS Protocol, Version 1.0, T. Dierks. Certicom, C. Allen. Certicom, January 1999.

Acknowledgements

This section is non normative.

The editor would like to thank Ian Hickson and everyone in the WHATWG community who has written the initial proposal for this specification.