To enable Web applications to communicate with each other in local area
networks, and to maintain bidirectional communications with their
originating server, this specification introduces the Connection interface.
The Window interface provides three
constructors for creating Connection objects: TCPConnection(), for creating a direct
(possibly encrypted) link to another node on the Internet using TCP/IP;
LocalBroadcastConnection(),
for creating a connection to any listening peer on a local network (which
could be a local TCP/IP subnet using UDP, a Bluetooth PAN, or another kind
of network infrastructure); and PeerToPeerConnection(), for a
direct peer-to-peer connection (which could again be over TCP/IP,
Bluetooth, IrDA, or some other type of network).
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.
This section is non-normative.
An introduction to the client-side and server-side of using the direct connection APIs.
An example of a party-line implementation of a broadcast service, and direct peer-to-peer chat for direct local connections.
Connection interfaceinterface Connection {
readonly attribute DOMString network;
readonly attribute DOMString peer;
readonly attribute int readyState;
attribute EventListener onopen;
attribute EventListener onread;
attribute EventListener onclose;
void send(in DOMString data);
void disconnect();
};
Connection objects must also
implement the EventTarget interface. [DOM3EVENTS]
When a Connection object is
created, the UA must try to establish a connection, as described in the
sections below describing each connection type.
The network attribute
represents the name of the network connection (the value depends on the
kind of connection being established). The peer attribute identifies the
remote host for direct (non-broadcast) connections.
The network attribute must be set as soon as the
Connection object is created, and
keeps the same value for the lifetime of the object. 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:
Once a connection is established, the readyState attribute's value must be
changed to 1, and the open event must be fired on the Connection object.
When data is received, the read event will be fired on the Connection object.
When the connection is closed, the readyState attribute's value must be
changed to 2, and the close event must be fired on the Connection 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, and close), and unregister their previous value if
any.
The send()
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 behaviour 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.
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;
readonly attribute DOMString source;
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 initConnectionReadEvent()
and initConnectionReadEventNS()
methods must initialise the event in a manner analogous to the
similarly-named methods in the DOM3 Events interfaces. [DOM3EVENTS]
The data attribute
represents the data that was transmitted from the peer.
The source attribute
represents the name of the peer. This is primarily useful on broadcast
connections; on direct connections it is equal to the peer attribute on the
Connection object.
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.
The TCPConnection(subdomain,
port, secure)
constructor on the Window interface
returns a new object implementing the Connection interface, set up for a direct
connection to a specified host on the page's domain.
When this constructor is invoked, the following steps must be followed.
First, if the domain part of the script's origin is not a host name (e.g. it is an IP address) then the UA must raise a security exception. 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 domain part of the script's origin. Otherwise, the subdomain argument is prepended to the domain part of the script's origin with a dot separating the two strings, and that is the target host.
If either:
...then the UA must raise a security 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 exception.
The user agent may also raise a security 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 Connection 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, and its network
attribute must be set to the same value as the peer attribute.
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 backgound, 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.
The LocalBroadcastConnection()
constructor on the Window interface
returns a new object implementing the Connection interface, set up to broadcast
on the local network.
When this constructor is invoked, a new Connection object must be created.
The network attribute of the object must be set to
the string representing the script's domain in IDNA
format. If this string cannot be obtained, then the user agent must
raise a security exception exception when the
constructor is called.
The peer
attribute must be set to the empty string.
The object must then be returned, unless, for some reason, permission to broadcast on the local network is to be denied. In the latter case, a security exception must be raised instead. User agents may deny such permission for any reason, for example a user preference.
If the object is returned (i.e. if no exception is raised), the user agent must the begin broadcasting and listening on the local network, in the background, as described below. The user agent may define "the local network" in any way it considers appropriate and safe; for instance the user agent may ask the user which network (e.g. Bluetooth, IrDA, Ethernet, etc) the user would like to broadcast on before beginning broadcasting.
UAs may broadcast and listen on multiple networks at once. For example, the UA could broadcast on both Bluetooth and Wifi at the same time.
As soon as the object is returned, the connection has been established, which implies that the
open event
must be fired. Broadcast connections are never closed.
Should we drop this altogether? Letting people fill the local network with garbage seems unwise.
We need to register a UDP port for this. For now this spec refers to port 18080/udp.
Since this feature requires that the user agent listen to a particular port, some platforms might prevent more than one user agent per IP address from using this feature at any one time.
On TCP/IP networks, broadcast connections transmit data using UDP over port 18080.
When the send(data) method is invoked on a Connection object that was created by the
LocalBroadcastConnection()
constructor, the user agent must follow these steps:
network
attribute of the Connection
object, a U+0020 SPACE character, a U+0002 START OF TEXT character, and
the data argument.
INDEX_SIZE_ERR DOM exception and stop.
When a broadcast connection is opened on a TCP/IP network, the user agent should listen for UDP packets on port 18080.
When the user agent receives a packet on port 18080, the user agent must
attempt to decode that packet's data as UTF-8. If the data is not fully
correct UTF-8 (i.e. if there are decoding errors) then the packet must be
ignored. Otherwise, the user agent must check to see if the decoded string
contains a U+0020 SPACE character. If it does not, then the packet must
again be ignored (it might be a peer discovery packet from a PeerToPeerConnection()
constructor). If it does then the user agent must split the string at the
first space character. All the characters before the space are then known
as d, and all the characters after the space are known
as s. If s is not at least one
character long, or if the first character of s is not
a U+0002 START OF TEXT character, then the packet must be ignored. (This
allows for future extension of this protocol.)
Otherwise, for each Connection
object that was created by the LocalBroadcastConnection()
constructor and whose network attribute exactly matches d, a read event must be fired on the Connection object. The string s, with the first character removed, must be used as the
data,
and the source IP address of the packet as the source.
Making the source IP available means that if two or more machines in a private network can be made to go to a hostile page simultaneously, the hostile page can determine the IP addresses used locally (i.e. on the other side of any NAT router). Is there some way we can keep link-local IP addresses secret while still allowing for applications to distinguish between multiple participants?
Does anyone know enough about Bluetooth to write this section?
Does anyone know enough about IrDA to write this section?
The PeerToPeerConnection()
constructor on the Window interface
returns a new object implementing the Connection interface, set up for a direct
connection to a user-specified host.
When this constructor is invoked, a new Connection object must be created.
The network attribute of the object must be set to
the string representing the script's domain in IDNA
format. If this string cannot be obtained, then the user agent must
raise a security exception exception when the
constructor is called.
The peer
attribute must be set to the empty string.
The object must then be returned, unless, for some reason, permission to establish peer-to-peer connections is generally disallowed, for example due to administrator settings. In the latter case, a security exception must be raised instead.
The user agent must then, typically while the script resumes execution, find a remote host to establish a connection to. To do this it must start broadcasting and listening for peer discovery messages and listening for incoming connection requests on all the supported networks. How this is performed depends on the type of network and is described below.
The UA should inform the user of the clients that are detected, and allow the user to select one to connect to. UAs may also allow users to explicit specify hosts that were not detected, e.g. by having the user enter an IP address.
If an incoming connection is detected before the user specifies a target host, the user agent should ask the user to confirm that this is the host they wish to connect to. If it is, the connection should be accepted and the UA will act as the server in this connection. (Which UA acts as the server and which acts as the client is not discernible at the DOM API level.)
If no incoming connection is detected and if the user specifies a particular target host, a connection should be established to that host, with the UA acting as the client in the connection.
No more than one connection must be established per Connection object, so once a connection has
been established, the user agent must stop listening for further
connections (unless, or until such time as, another Connection object is being created).
If at any point the user cancels the connection process or the remote host refuses the connection, then the user agent must act as if it had closed the connection, and stop trying to connect.
Should we replace this section with something that uses Rendez-vous/zeroconf or equivalent?
We need to register ports for this. For now this spec refers to port 18080/udp and 18080/tcp.
Since this feature requires that the user agent listen to a particular port, some platforms might prevent more than one user agent per IP address from using this feature at any one time.
When using TCP/IP, broadcasting peer discovery messages must be done by
creating UDP packets every few seconds containing as their data the value
of the connection's network attribute, encoded as UTF-8, with the
source and destination ports being set to 18080 and appropriate length and
checksum fields, and sending these packets to address (in IPv4)
255.255.255.255 or (in IPv6) ff02::1, as appropriate.
Listening for peer discovery messages must be done by examining incoming
UDP packets on port 18080. IPv6 applications will also
have to enable reception from the ff02::1 address. If their payload
is exactly byte-for-byte equal to a UTF-8 encoded version of the value of
the connection's network attribute, then the source address of
that packet represents the address of a host that is ready to accept a
peer-to-peer connection, and it should therefore be offered to the user.
Incoming connection requests must be listened for on TCP port 18080. If an incoming connection is received, the UA must act as a server, as described in the section entitled servers accepting connections over TCP.
If no incoming connection requests are accepted and the user instead specifies a target host to connect to, the UA acts as a client: the user agent must attempt to connect to the user-specified host on port 18080, as described in the section entitled clients connecting over TCP.
Once the connection is established, the UA must act as described in the section entitled sending and receiving data over TCP.
This specification does not include a way to establish secure (encrypted) peer-to-peer connections at this time. If you can see a good way to do this, let me know.
Does anyone know enough about Bluetooth to write this section?
Does anyone know enough about IrDA to write this section?
The same protocol is used for TCPConnection and PeerToPeerConnection connection
types. This section describes how such 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).
This section defines the client-side requirements of the protocol used
by the TCPConnection and PeerToPeerConnection connection
types.
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.
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. For UAs
these are the requirements for the server part of PeerToPeerConnections.
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.
When the send(data) method is invoked on the connection's
corresponding Connection 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 Connection 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 media 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).
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.
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)