WebSocketRelay class

A reference frame relay for WebSocketTransport peers that cannot reach each other directly (typically: browsers, or devices on different networks).

Every client connects with a WebSocket, announces itself (hello <node>), learns about the other clients (join / left lines), and exchanges addressed binary envelopes; the relay routes each envelope to its to node. The relay is not trusted with data: payloads are end-to-end encrypted by Passnote before they reach the transport, so the relay sees only node ids, public room tags, and ciphertext.

Deployment warning

The relay has no authentication, and that means more than "anyone may connect": anyone who can reach it can claim any node id that is not connected at that moment. The squatter then receives every envelope addressed to that id — still ciphertext, but the full metadata graph (who talks to the node, frame sizes, timing) — and the real node is refused until the squatter leaves, a denial of service it cannot tell from an outage. An id that is already connected cannot be taken over, and dead connections are reaped by ping so a dropped node can reclaim its id, but pre-claiming is always possible. Run the relay only on a network you control, or behind an authenticating proxy. In the same breath: open connections, frame size, node-id length, and time-to-hello are bounded only by maxClients, maxFrameBytes, and helloTimeout — resource hygiene, not protection.

This is a reference, not a product: it binds one port, keeps everything in memory, and has no persistence. Run it with dart run passnote_lan:relay --port 9473, or host it in-process:

final relay = await WebSocketRelay.bind(port: 9473);
print('relay on ${relay.port}');

Properties

connectedNodes → Iterable<String>
The node ids currently connected.
no setter
hashCode → int
The hash code for this object.
no setterinherited
helloTimeout → Duration
How long a connection may stay open without sending its hello.
final
maxClients → int
Maximum simultaneously connected clients.
final
maxFrameBytes → int
Maximum size of one relayed envelope in bytes.
final
port → int
The port the relay is listening on.
no setter
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited

Methods

close() → Future<void>
Stops the relay and disconnects every client.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() → String
A string representation of this object.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited

Static Methods

bind({required int port, int maxClients = 256, int maxFrameBytes = 4 << 20, Duration helloTimeout = const Duration(seconds: 10)}) → Future<WebSocketRelay>
Binds the relay on port (0 = an ephemeral port).

Constants

relayFullCode → const int
Application close code for "relay full" (dart:io only permits reserved codes or the 3000-4999 range).