This specification does not currently reflect the way Named Web Sockets currently work at https://github.com/namedwebsockets/networkwebsockets!
This specification defines a bootstrap mechanism for creating, binding and connecting WebSocket peers together on a local machine or on a local network that share the same service name. Named WebSockets can be created from both web applications and native applications to create communications bridges between and among themselves.
This specification introduces the LocalWebSocket
and NetworkWebSocket
interfaces and the algorithms required to create, bind, advertise and discover other WebSocket peers on the local machine and the local network.
By enabling different peers on local machines and local networks to discover and connect with each other we enable new sharing channels to be established. The following diagram illustrates some of the high-level sharing enabled by Named WebSockets.
Implementors need to be aware that this specification is extremely unstable. Implementors who are not taking part in the discussions will find the specification changing out from under them in incompatible ways. Vendors interested in implementing this specification before it eventually reaches the Candidate Recommendation phase should subscribe to the repository on GitHub and take part in the discussions.
This section shows how developers can make use of the various features of this specification.
The following shows how a web page can create a local machine broadcast channel.
var ws = new LocalWebSocket("com.example.bootstrapservice");
The returned object implements the WebSocket
interface and thus can be used as a normal WebSocket object. Sending and receiving directly on the returned object broadcasts messages to all local machine peers.
ws.addEventListener('open', function(evt) { ws.send("New broadcast message sent on local service 'com.example.bootstrapservice'"); }, false); ws.addEventListener('message', function(evt) { console.log("Broadcast message received on local service 'com.example.bootstrapservice'"); }, false);
Whenever another peer registers on the local machine that shares the same service name (i.e. "com.example.bootstrapservice") and an entangled websocket connection has been established between these peers, then a connect
event containing a WebSocket connection toward the newly discovered peer will be fired on the root object.
ws.addEventListener('connect', function(evt) { console.log("New peer detected on local service 'com.example.bootstrapservice'"); var peerWebSocket = evt.target; /* Use peerWebSocket object for direct p2p communication with newly established WebSocket peer */ }, false);
The following shows how a web page can create a local network broadcast channel.
var ws = new NetworkWebSocket("com.example.bootstrapservice");
The returned object implements the WebSocket
interface and thus can be used as a normal WebSocket object. Sending and receiving directly on the returned object broadcasts messages to all local network peers.
ws.addEventListener('open', function(evt) { ws.send("New broadcast message sent on network service 'com.example.bootstrapservice'"); }, false); ws.addEventListener('message', function(evt) { console.log("Broadcast message received on network service 'com.example.bootstrapservice'"); }, false);
Whenever another peer registers on the local network or the local machine (created via the NetworkWebSocket
interface) that shares the same service name (i.e. "com.example.bootstrapservice") and an entangled websocket connection has been established between these peers, then a connect
event containing a WebSocket connection toward the newly discovered peer will be fired on the root object.
ws.addEventListener('connect', function(evt) { console.log("New peer detected on network service 'com.example.bootstrapservice'"); var peerWebSocket = evt.target; /* Use peerWebSocket object for direct p2p communication with newly established WebSocket peer */ }, false);
Named WebSockets are useful in a variety of collaborative local device and local network scenarios:
Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.
Some conformance requirements are phrased as requirements on attributes, methods or objects. Such requirements are to be interpreted as requirements on user agents.
Conformance requirements phrased as algorithms or specific steps MAY be implemented in any manner, so long as the end result is equivalent. (In particular, the algorithms defined in this specification are intended to be easy to follow, and not intended to be performant.)
The only conformance class defined by this specification is a user agent.
User agents MAY impose implementation-specific limits on otherwise unconstrained inputs, e.g. to prevent denial of service attacks, to guard against running out of memory, or to work around platform-specific limitations.
When support for a feature is disabled (e.g. as an emergency measure to mitigate a security problem, or to aid in development, or for performance reasons), user agents MUST act as if they had no support for the feature whatsoever, and as if the feature was not mentioned in this specification. For example, if a particular feature is accessed via an attribute in a Web IDL interface, the attribute itself would be omitted from the objects that implement that interface - leaving the attribute on the object but making it return null or throw an exception is insufficient.
This specification relies on other underlying specifications:
The construction "a Foo
object", where Foo
is actually an interface, is sometimes
used instead of the more accurate "an object implementing the interface Foo
".
The term DOM is used to refer to the API set made available to scripts in Web applications, and does not
necessarily imply the existence of an actual Document
object or of any other Node
objects as defined in the DOM Core specifications. [[!DOM4]]
An IDL attribute is said to be getting when its value is being retrieved (e.g. by author script), and is said to be setting when a new value is assigned to it.
A valid channel name is a string used to federate peers that contains from 3 to 128 Unicode characters in the ranges U+002D to U+002E, U+0030 to U+0039, U+0041 to U+005A, U+005F, U+0061 to U+007A.
The local multicast address is a UDP socket bound to both the IPv4 loopback address 127.0.0.1:5352
and the IPv6 loopback address [::1]:5352
.
The network multicast address is a UDP socket bound to both the IPv4 address 224.0.0.251:5353
and the IPv6 address [FF02::FB]:5353
(also known as the standard [[!MDNS]] listener endpoints).
A user agent MUST listen for new Named WebSocket DNS-SD [[!DNS-SD]] broadcasts from other user agents on both the local multicast address and the network multicast address. Additionally, a user agent MUST managing the advertising of locally-created Named WebSockets objects via [[!DNS-SD]] from a random locally-bound port toward either the local multicast address or the network multicast address according to the algorithms defined in this specification.
All implementations MUST use the SO_REUSEPORT
and SO_REUSEADDR
options so all
user agents are able to bind to the same local multicast address and network multicast address. Additional guidelines to avoid conflicts between multiple mDNS responders running on the same machine are provided and MUST be followed by implementations from Considerations for Multiple Responders on the Same Machine. [[!MDNS]]
A local WebSocket URL is a standard WebSocket URL with a scheme of ws
, a host of localhost
, a port and a path component that identifies a single peer registered or discovered on the local multicast address.
A network WebSocket URL is a standard WebSocket URL with a scheme of ws
, a host corresponding to a resolvable host name on the local network, a port and a path component that identifes a single peer registered or discovered on the network multicast address.
The list of active local WebSockets is a dynamic list that contains active LocalWebSocket
objects created by the user agent.
The list of active network WebSockets is a dynamic list that contains active NetworkWebSocket
objects created by the user agent.
Each Named WebSocket object (a LocalWebSocket
object or a NetworkWebSocket
object) has its own peer list that tracks WebSocket connections from itself to remote Named WebSocket peers.
The local broadcast list is a dynamic map of channel name to zero or more peer WebSocket
connections. When a new Named WebSocket service is detected on the local multicast address then it will be added to this list.
The network broadcast list is a dynamic map of channel name to zero or more peer WebSocket
connections. When a new Named WebSocket service is detected on the network multicast address then it will be added to this list.
LocalWebSocket
interface[Constructor(DOMString channel)] interface LocalWebSocket : WebSocket { // peer establishment attribute EventHandler onconnect; }
The LocalWebSocket(channel)
constructor takes one argument, channel, that specifies the local machine service name to which to connect.
When the LocalWebSocket()
constructor is invoked, the UA must run these steps:
SyntaxError
exception and abort these steps.
/
" followed by channel, followed by "/
", followed by peer id, followed by "/
", followed by a remote peer id placeholder "%s
" (e.g. /myservicename/fa4c372c-f557-11e3-981d-b2227cce2b54/%s
).
User agents MAY define the path component as they wish provided the generated path is globally unique and a remote peer id placeholder ("%s
") is included in the resulting path (i.e. /fa4c372c-f557-11e3-981d-b2227cce2b54/myservicename?%s
or /services?id=fa4c372c-f557-11e3-981d-b2227cce2b54&peerId=%s&serviceName=myservicename
are also valid path components).
[
", followed by peer id, followed by "]
", followed by "._ws._tcp.local.
". e.g. _ws._tcp.local. 10 IN PTR myservicename[fa4c372c...]._ws._tcp.local.
myservicename[fa4c372c...]._ws._tcp.local. 10 IN SRV 10 1 32541 localhost
path=
" followed by the newly created local WebSocket URL's path component. e.g. myservicename[fa4c372c...]._ws._tcp.local. 10 IN TXT "path=/myservicename/fa4c372c.../%s"
_ws._tcp.local.
services according to the algorithms defined in [[!MDNS]].
The LocalWebSocket
constructor must be visible when the script's global object is either a Window
object or an object implementing the WorkerUtils
interface.
NetworkWebSocket
interface[Constructor(DOMString channel)] interface NetworkWebSocket : WebSocket { // peer establishment attribute EventHandler onconnect; }
The NetworkWebSocket(channel)
constructor takes one argument, channel, that specifies the local network service name to which to connect.
When the NetworkWebSocket()
constructor is invoked, the UA must run these steps:
SyntaxError
exception and abort these steps.
/
" followed by channel, followed by "/
", followed by peer id, followed by "/
", followed by a remote peer id placeholder "%s
" (e.g. /myservicename/j343h93x/%s
).
User agents MAY define the path component as they wish provided the generated path is globally unique and a remote peer id placeholder ("%s
") is included in the resulting path (i.e. /j343h93x/myservicename?%s
or /services?id=j343h93x&peerId=%s&serviceName=myservicename
are also valid path components).
[
", followed by peer id, followed by "]
", followed by "._ws._tcp.local.
". e.g. _ws._tcp.local. 10 IN PTR myservicename[j343h93x]._ws._tcp.local.
myservicename[j343h93x]._ws._tcp.local. 10 IN SRV 10 1 23956 MyComputer.local.
path=
" followed by the newly created network WebSocket URL's path component. e.g. myservicename[j343h93x]._ws._tcp.local. 10 IN TXT "path=/myservicename/j343h93x/%s"
MyComputer.local. 10 IN A 10.112.0.223
MyComputer.local. 10 IN AAAA fe80::7aca:39ff:feb4:42c1
_ws._tcp.local.
services according to the algorithms defined in [[!MDNS]].
The NetworkWebSocket
constructor must be visible when the script's global object is either a Window
object or an object implementing the WorkerUtils
interface.
@TBD
A user agent MUST actively search for new Named WebSocket peers via both the local multicast address and the network multicast address.
When a Named WebSocket peer is discovered as a result of running an mDNS Query for _ws._tcp.local.
services against either the local multicast address or the network multicast address then a user agent MUST run the following steps:
%s
") in the service URL with the peer id of the active WebSocket.
WebSocket
object with a URL of peering URL.
WebSocket
object with a URL of service URL.
connect
, a target
of client WebSocket, which does not bubble, is not cancelable, and has no default action.
A user agent MUST listen for new Named WebSocket broadcasts from other agents on both the local multicast address and the network multicast address using standard [[!MDNS]] techniques.
The rule to obtain an advertised Named WebSocket service name is as follows:
The rule to obtain an advertised Named WebSocket service id is as follows:
The rule to obtain an advertised Named WebSocket service URL is as follows:
ws://
", followed by host, followed by ":
", followed by port, followed by path.
The user agent MUST allow remote peers to establish WebSocket connections based on the services that it currently manages.
When a new incoming WebSocket connection is established from a remote peer that has independently discovered a peer service running on the current user agent then the user agent MUST run the following steps.
WebSocket
object representing the new incoming WebSocket connection.%s
") is present in service URL then add the WebSocket connection object to the appropriate broadcast list against the resolved service name and abort any remaining steps.connect
, a target
of server WebSocket, which does not bubble, is not cancelable, and has no default action.
When a new Named WebSocket is created via the LocalWebSocket()
or NetworkWebSocket()
constructors the resulting object MUST act as a broadcast channel toward all peer WebSocket connections contained in either the local broadcast list or the network broadcast list, as appropriate, that share the same valid channel name. Thus, if send()
is called on a Named WebSocket object then the user agent MUST relay the sent message toward all matching broadcast WebSocket connections in the appropriate broadcast list. All broadcast WebSocket connections other than the sender MUST receive the sent message, by emitting a standard WebSocket message
event against the broadcast WebSocket object (either a LocalWebSocket
or NetworkWebSocket
object).