W3C

HTML 5

A vocabulary and associated APIs for HTML and XHTML

← 5. EditingTable of contents7. Repetition templates →

6. Communication

6.1 Event definitions

Messages in cross-document messaging and in server-sent DOM events, use the message event.

The following interface is defined for this event:

interface MessageEvent : Event {
  readonly attribute DOMString data;
  readonly attribute DOMString origin;
  readonly attribute DOMString lastEventId;
  readonly attribute Window source;
  void initMessageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString dataArg, in DOMString originArg, in DOMString lastEventIdArg, in Window sourceArg);
  void initMessageEventNS(in DOMString namespaceURI, in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString dataArg, in DOMString originArg, in DOMString lastEventIdArg, in Window sourceArg);
};

The initMessageEvent() and initMessageEventNS() 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 message being sent.

The origin attribute represents, in cross-document messaging, the origin of the document that sent the message (typically the scheme, hostname, and port of the document, but not its path or fragment identifier).

The lastEventId attribute represents, in server-sent dom events, the last event ID string of the event source.

The source attribute represents, in cross-document messaging, the Window from which the message came.

6.2 Server-sent DOM events

This section describes a mechanism for allowing servers to dispatch DOM events into documents that expect it. The event-source element provides a simple interface to this mechanism.

6.2.1 The RemoteEventTarget interface

Any object that implements the EventTarget interface must also implement the RemoteEventTarget interface.

interface RemoteEventTarget {
  void addEventSource(in DOMString src);
  void removeEventSource(in DOMString src);
};

When the addEventSource(src) method is invoked, the user agent must add the URI specified in src to the list of event sources for that object. The same URI can be registered multiple times.

When the removeEventSource(src) method is invoked, the user agent must remove the URI specified in src from the list of event sources for that object. If the same URI has been registered multiple times, removing it must remove only one instance of that URI for each invocation of the removeEventSource() method.

Relative URIs must be resolved relative to ....

6.2.2 Connecting to an event stream

Each object implementing the EventTarget and RemoteEventTarget interfaces has a list of event sources that are registered for that object.

When a new URI is added to this list, the user agent should, as soon as all currently executing scripts (if any) have finished executing, and if the specified URI isn't removed from the list before they do so, fetch the resource identified by that URI.

When an event source is removed from the list of event sources for an object, if that resource is still being fetched, then the relevant connection must be closed.

Since connections established to remote servers for such resources are expected to be long-lived, UAs should ensure that appropriate buffering is used. In particular, while line buffering may be safe if lines are defined to end with a single U+000A LINE FEED character, block buffering or line buffering with different expected line endings can cause delays in event dispatch.

Each event source in the list must have associated with it the following:

In general, the semantics of the transport protocol specified by the URIs for the event sources must be followed, including HTTP caching rules.

For HTTP connections, the Accept header may be included; if included, it must contain only formats of event framing that are supported by the user agent (one of which must be text/event-stream, as described below).

Other formats of event framing may also be supported in addition to text/event-stream, but this specification does not define how they are to be parsed or processed.

Such formats could include systems like SMS-push; for example servers could use Accept headers and HTTP redirects to an SMS-push mechanism as a kind of protocol negotiation to reduce network load in GSM environments.

User agents should use the Cache-Control: no-cache header in requests to bypass any caches for requests of event sources.

If the event source's last event ID string is not the empty string, then a Last-Event-ID HTTP header must be included with the request, whose value is the value of the event source's last event ID string.

For connections to domains other than the document's domain, the semantics of the Access-Control HTTP header must be followed. [ACCESSCONTROL]

HTTP 200 OK responses with a Content-Type header specifying the type text/event-stream that are either from the document's domain or explicitly allowed by the Access-Control HTTP headers must be processed line by line as described below.

For the purposes of such successfully opened event streams only, user agents should ignore HTTP cache headers, and instead assume that the resource indicates that it does not wish to be cached.

If such a resource completes loading (i.e. the entire HTTP response body is received or the connection itself closes), the user agent should request the event source resource again after a delay equal to the reconnection time of the event source.

HTTP 200 OK responses that have a Content-Type other than text/event-stream (or some other supported type), and HTTP responses whose Access-Control headers indicate that the resource are not to be used, must be ignored and must prevent the user agent from refetching the resource for that event source.

HTTP 201 Created, 202 Accepted, 203 Non-Authoritative Information, and 206 Partial Content responses must be treated like HTTP 200 OK responses for the purposes of reopening event source resources. They are, however, likely to indicate an error has occurred somewhere and may cause the user agent to emit a warning.

HTTP 204 No Content, and 205 Reset Content responses must be treated as if they were 200 OK responses with the right MIME type but no content, and should therefore cause the user agent to refetch the resource after a delay equal to the reconnection time of the event source.

HTTP 300 Multiple Choices responses should be handled automatically if possible (treating the responses as if they were 302 Found responses pointing to the appropriate resource), and otherwise must be treated as HTTP 404 responses.

HTTP 301 Moved Permanently responses must cause the user agent to reconnect using the new server specified URI instead of the previously specified URI for all subsequent requests for this event source. (It doesn't affect other event sources with the same URI unless they also receive 301 responses, and it doesn't affect future sessions, e.g. if the page is reloaded.)

HTTP 302 Found, 303 See Other, and 307 Temporary Redirect responses must cause the user agent to connect to the new server-specified URI, but if the user agent needs to again request the resource at a later point, it must return to the previously specified URI for this event source.

HTTP 304 Not Modified responses should be handled like HTTP 200 OK responses, with the content coming from the user agent cache. A new request should then be made after a delay equal to the reconnection time of the event source.

HTTP 305 Use Proxy, HTTP 401 Unauthorized, and 407 Proxy Authentication Required should be treated transparently as for any other subresource.

Any other HTTP response code not listed here should cause the user agent to stop trying to process this event source.

DNS errors must be considered fatal, and cause the user agent to not open any connection for that event source.

For non-HTTP protocols, UAs should act in equivalent ways.

6.2.3 Parsing an event stream

This event stream format's MIME type is text/event-stream.

The event stream format is (in pseudo-BNF):

<stream>          ::= <bom>? <event>*
<event>           ::= [ <comment> | <field> ]* <newline>
<comment>         ::= <colon> <any-char>* <newline>
<field>           ::= <name-char>+ [ <colon> <space>? <any-char>* ]? <newline>

# characters:
<bom>             ::= a single U+FEFF BYTE ORDER MARK character
<space>           ::= a single U+0020 SPACE character (' ')
<newline>         ::= a U+000D CARRIAGE RETURN character
                      followed by a U+000A LINE FEED character
                      | a single U+000D CARRIAGE RETURN character
                      | a single U+000A LINE FEED character
                      | the end of the file
<colon>           ::= a single U+003A COLON character (':')
<name-char>       ::= a single Unicode character other than
                      U+003A COLON, U+000D CARRIAGE RETURN and U+000A LINE FEED
<any-char>        ::= a single Unicode character other than
                      U+000D CARRIAGE RETURN and U+000A LINE FEED

Event streams in this format must always be encoded as UTF-8.

Lines must be separated by either a U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF) character pair, a single U+000A LINE FEED (LF) character, or a single U+000D CARRIAGE RETURN (CR) character.

6.2.4 Interpreting an event stream

Bytes or sequences of bytes that are not valid UTF-8 sequences must be interpreted as the U+FFFD REPLACEMENT CHARACTER.

One leading U+FEFF BYTE ORDER MARK character must be ignored if any are present.

The stream must then be parsed by reading everything line by line, with a U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF) character pair, a single U+000A LINE FEED (LF) character, a single U+000D CARRIAGE RETURN (CR) character, and the end of the file being the four ways in which a line can end.

When a stream is parsed, a data buffer and an event name buffer must be associated with it. They must be initialized to the empty string

Lines must be processed, in the order they are received, as follows:

If the line is empty (a blank line)

Dispatch the event, as defined below.

If the line starts with a U+003A COLON character (':')

Ignore the line.

If the line contains a U+003A COLON character (':') character

Collect the characters on the line before the first U+003A COLON character (':'), and let field be that string.

Collect the characters on the line after the first U+003A COLON character (':'), and let value be that string. If value starts with a single U+0020 SPACE character, remove it from value.

Process the field using the steps described below, using field as the field name and value as the field value.

Otherwise, the string is not empty but does not contain a U+003A COLON character (':') character

Process the field using the steps described below, using the whole line as the field name, and the empty string as the field value.

Once the end of the file is reached, the user agent must dispatch the event one final time, as defined below.

The steps to process the field given a field name and a field value depend on the field name, as given in the following list. Field names must be compared literally, with no case folding performed.

If the field name is "event"

Set the event name buffer the to field value.

If the field name is "data"

If the data buffer is not the empty string, then append a single U+000A LINE FEED character to the data buffer. Append the field value to the data buffer.

If the field name is "id"

Set the event stream's last event ID to the field value.

If the field name is "retry"

If the field value consists of only characters in the range U+0030 DIGIT ZERO ('0') U+0039 DIGIT NINE ('9'), then interpret the field value as an integer in base ten, and set the event stream's reconnection time to that integer. Otherwise, ignore the field.

Otherwise

The field is ignored.

When the user agent is required to dispatch the event, then the user agent must act as follows:

  1. If the data buffer is an empty string, set the data buffer and the event name buffer to the empty string and abort these steps.

  2. If the event name buffer is not the empty string but is also not a valid NCName, set the data buffer and the event name buffer to the empty string and abort these steps.

  3. Otherwise, create an event that uses the MessageEvent interface, with the event name message, which does not bubble, is cancelable, and has no default action. The data attribute must be set to the value of the data buffer, the origin attribute must be set to the origin of the event stream's URI, the lastEventId attribute must be set to the last event ID string of the event source, and the source attribute must be set to null.

  4. If the event name buffer has a value other than the empty string, change the type of the newly created event to equal the value of the event name buffer.

  5. Set the data buffer and the event name buffer to the empty string.

  6. Dispatch the newly created event at the RemoteEventTarget object to which the event stream is registered.

If an event doesn't have an "id" field, but an earlier event did set the event source's last event ID string, then the event's lastEventId field will be set to the value of whatever the last seen "id" field was.

The following event stream, once followed by a blank line:

data: YHOO
data: -2
data: 10

...would cause an event message with the interface MessageEvent to be dispatched on the event-source element, whose data attribute would contain the string YHOO\n-2\n10 (where \n represents a newline).

This could be used as follows:

<event-source src="http://stocks.example.com/ticker.php"
              onmessage="var data = event.data.split('\n'); updateStocks(data[0], data[1], data[2]);">

...where updateStocks() is a function defined as:

function updateStocks(symbol, delta, value) { ... }

...or some such.

The following stream contains four blocks. The first block has just a comment, and will fire nothing. The second block has two fields with names "data" and "id" respectively; an event will be fired for this block, with the data "first event", and will then set the last event ID to "1" so that if the connection died between this block and the next, the server would be sent a Last-Event-ID header with the value "1". The third block fires an event with data "second event", and also has an "id" field, this time with no value, which resets the last event ID to the empty string (meaning no Last-Event-ID header will now be sent in the event of a reconnection being attempted). Finally the last block just fires an event with the data "third event". Note that the last block doesn't have to end with a blank line, the end of the stream is enough to trigger the dispatch of the last event.

: test stream

data: first event
id: 1

data: second event
id

data: third event

The following stream fires just one event:

data

data
data

data:

The first and last blocks do nothing, since they do not contain any actual data (the data buffer remains at the empty string, and so nothing gets dispatched). The middle block fires an event with the data set to a single newline character.

The following stream fires two identical events:

data:test

data: test

This is because the space after the colon is ignored if present.

6.2.5 Notes

Legacy proxy servers are known to, in certain cases, drop HTTP connections after a short timeout. To protect against such proxy servers, authors can include a comment line (one starting with a ':' character) every 15 seconds or so.

Authors wishing to relate event source connections to each other or to specific documents previously served might find that relying on IP addresses doesn't work, as individual clients can have multiple IP addresses (due to having multiple proxy servers) and individual IP addresses can have multiple clients (due to sharing a proxy server). It is better to include a unique identifier in the document when it is served and then pass that identifier as part of the URI in the src attribute of the event-source element.

Implementations that support HTTP's per-server connection limitation might run into trouble when opening multiple pages from a site if each page has an event-source to the same domain. Authors can avoid this using the relatively complex mechanism of using unique domain names per connection, or by allowing the user to enable or disable the event-source functionality on a per-page basis.

6.3 Network connections

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.

6.3.1 Introduction

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.

6.3.2 The Connection interface

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

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

6.3.3 Connection 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;
  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.

6.3.4 TCP connections

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 host 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 host part of the script's origin. Otherwise, the subdomain argument is prepended to the host 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 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.

6.3.5 Broadcast connections

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.

6.3.5.1. Broadcasting over TCP/IP

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:

  1. Create a string consisting of the value of the network attribute of the Connection object, a U+0020 SPACE character, a U+0002 START OF TEXT character, and the data argument.
  2. Encode the string as UTF-8.
  3. If the resulting byte stream is longer than 65487 bytes, raise an INDEX_SIZE_ERR DOM exception and stop.
  4. Create a UDP packet whose data is the byte stream, with the source and destination ports being 18080, and with appropriate length and checksum fields. Transmit this packet to IPv4 address 255.255.255.255 or IPv6 address ff02::1, as appropriate. IPv6 applications will also have to enable reception from this address.

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?

6.3.5.2. Broadcasting over Bluetooth

Does anyone know enough about Bluetooth to write this section?

6.3.5.3. Broadcasting over IrDA

Does anyone know enough about IrDA to write this section?

6.3.6 Peer-to-peer connections

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.

6.3.6.1. Peer-to-peer connections over TCP/IP

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.

6.3.6.2. Peer-to-peer connections over Bluetooth

Does anyone know enough about Bluetooth to write this section?

6.3.6.3. Peer-to-peer connections over IrDA

Does anyone know enough about IrDA to write this section?

6.3.7 The common protocol for TCP-based connections

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

6.3.7.1. Clients connecting over TCP

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.

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

6.3.7.3. Sending and receiving data over TCP

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

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

6.3.9 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)

6.4 Cross-document messaging

Web browsers, for security and privacy reasons, prevent documents in different domains from affecting each other; that is, cross-site scripting is disallowed.

While this is an important security feature, it prevents pages from different domains from communicating even when those pages are not hostile. This section introduces a messaging system that allows documents to communicate with each other regardless of their source domain, in a way designed to not enable cross-site scripting attacks.

6.4.1 Processing model

When a script invokes the postMessage(message, targetOrigin) method on a Window object, the user agent must follow these steps:

  1. If the value of the targetOrigin argument is neither a single U+002A ASTERISK character ("*") nor a valid URI or IRI, then throw a SYNTAX_ERR exception and abort the overall set of steps. [RFC3986] [RFC3987]

  2. Return from the postMessage() method, but asynchronously continue running these steps.

  3. Wait for the Window object on which the method was invoked to have finished executing any pending scripts.

  4. If the targetOrigin argument has a value other than a single literal U+002A ASTERISK character ("*"), and the active document of the Window object on which the method was invoked does not have the same origin as targetOrigin, then abort these steps silently.

  5. Create an event that uses the MessageEvent interface, with the event name message, which does not bubble, is cancelable, and has no default action. The data attribute must be set to the value passed as the message argument to the postMessage() method, the origin attribute must be set to the serialization of the origin of the script that invoked the method, the lastEventId attribute must be set to the empty string, and the source attribute must be set to the Window object of the default view of the browsing context for which the Document object with which the script is associated is the active document.

  6. Dispatch the event created in the previous step at the Window object on which the method was invoked.

Authors should check the origin attribute to ensure that messages are only accepted from domains that they expect to receive messages from. Otherwise, bugs in the author's message handling code could be exploited by hostile sites.

Authors should not use the wildcard keyword ("*") in the targetOrigin argument in messages that contain any confidential information, as otherwise there is no way to guarantee that the message is only delivered to the recipient to which it was intended.

For example, if document A contains an object element that contains document B, and script in document A calls postMessage() on document B, then a message event will be fired on that element, marked as originating from document A. The script in document A might look like:

var o = document.getElementsByTagName('object')[0];
o.contentWindow.postMessage('Hello world', 'http://b.example.org/');

To register an event handler for incoming events, the script would use addEventListener() (or similar mechanisms). For example, the script in document B might look like:

document.addEventListener('message', receiver, false);
function receiver(e) {
  if (e.origin == 'http://example.com') {
    if (e.data == 'Hello world') {
      e.source.postMessage('Hello', e.origin);
    } else {
      alert(e.data);
    }
  }
}

This script first checks the domain is the expected domain, and then looks at the message, which it either displays to the user, or responds to by sending a message back to the document which sent the message in the first place.

The integrity of this API is based on the inability for scripts of one origin to post arbitrary events (using dispatchEvent() or otherwise) to objects in other origins (those that are not the same).

Implementors are urged to take extra care in the implementation of this feature. It allows authors to transmit information from one domain to another domain, which is normally disallowed for security reasons. It also requires that UAs be careful to allow access to certain properties but not others.