websocket-echo-chamber
v1.0.0
Published
Low-overhead implementation of a WebSocket communication hub.
Downloads
4
Readme
WebSocket Echo Chamber
Low-overhead implementation of a WebSocket communication hub.
Chambers are identified by URL. All connections to the same chamber will hear each other's messages reflected back and be notified when connections are made and closed.
Usage
npm start [<port> [<domain>]]
If domain
is specified, the Origin
header will be checked against
it. It should be a comma-separated list of permitted domains.
Example allowing local access during development:
npm start 8080 file://
You can include this in another project using npm:
npm install --save websocket-echo-chamber
Once added, you can start the server from the command line:
echo-chamber 8080 file://
Or create your own server programmatically:
const {EchoChamberHalls, WebSocketServer} = require('websocket-echo-chamber');
const domains = [];
// Max memory usage is approximately (bytes):
// (MAX_QUEUE_DATA + HEADERS_MAX_LENGTH) * CHAMBER_MAX_CONNECTIONS * MAX_CHAMBERS
// + some overhead from data structures
// Memory usage will typically be much lower (unless explicitly attacked)
// The values below result in ~0.25GB peak memory usage
const echoChamber = new EchoChamberHalls('/', domains, {
MAX_QUEUE_ITEMS: 1024,
MAX_QUEUE_DATA: 16 * 1024,
HEADERS_MAX_LENGTH: 1024,
CHAMBER_MAX_CONNECTIONS: 64,
MAX_CHAMBERS: 256,
});
// 2-person echo chambers do not require a queue, so we can support more of them
const p2EchoChamber = new EchoChamberHalls('/p2/', domains, {
MAX_QUEUE_ITEMS: 0,
MAX_QUEUE_DATA: 0,
HEADERS_MAX_LENGTH: 1024,
CHAMBER_MAX_CONNECTIONS: 2,
MAX_CHAMBERS: 512,
});
new WebSocketServer()
.addHandler(p2EchoChamber)
.addHandler(echoChamber)
.listen(8080, '127.0.0.1')
.then((server) => server.printListeningInfo(process.stdout));
Protocol
Connect to a chamber with:
socket = new WebSocket(baseURL + chamberName, ['echo']);
All received messages will begin with colon-separated metadata. Each item begins with a letter which denotes its type, followed by type-specific data. The metadata types are:
I<n>
: received when first connecting; gives the unique ID for this connectionH<n>
: "hi" received when a connection is madeB<n>
: "bye" received when a connection is closed or lostF<n>
: "from" the message which follows came from the noted connectionX
: "truncated" the preceeding message was truncated
After all metadata, there may be a newline followed by an arbitrary message. If there is no metadata, the message will start with a newline.
All sent messages will have metadata attached and be distributed to all other connections (excluding the one which sent the data).
User IDs are currently numeric, but may change to UUIDs or any alphanumeric format in the future.
See the sources in test-client
for an example.
Example server-to-client messages:
Begin connection to new room
New connection is assigned ID "100"
I100
Begin connection to existing room
Room already contains "3" and "22", new connection is assigned ID "29"
I29:H3:H22
Message received
Message sent from connection "19"
F19
Message here
(may contain extra newlines)
Partial message received
Message sent from connection "22" but connection is lost before all data is uploaded, or another data stream forced this one to close
F22
Partial messa
X
(the first message appears to complete normally, but is immediately
followed by a header-only message showing the error - X
= previous
message truncated)
Example client-to-server messages:
Send message to all connections except self
Message here
Send message to any arbitrary connection except self
(will favour long-lived connections which are currently idle)
T*
Message here
Send message to all connections including self
T**
Message here
Send message to specific connection(s) (can include self)
Send to connection "22" and "18"
T22,18
Message here