mirror of
https://github.com/brazilofmux/tinymux
synced 2026-08-13 00:23:11 -04:00
docs: the browser client connects DIRECTLY to netmux — correct #2215's README
The README merged in #2216 claimed browsers cannot reach netmux and that both transports require Hydra. Wrong on the central point: netmux serves WebSocket natively on its ordinary game ports (mux/src/websocket.cpp, RFC 6455) with first-byte protocol detection sharing each port between telnet and WebSocket (#1074/#2193, proto_detect_window), and the handshake accepts both /wsclient and / — which is exactly the path js/connection.js dials. The minimal browser deployment is netmux plus static files, no extra process; Hydra is the OPTIONAL layer for session resume, multi-game links, stored credentials, and gRPC-Web. The error came from concluding absence out of a truncated grep: the file listing was piped through head and mux/proxy's matches filled the window before mux/src/websocket.cpp appeared. A truncated listing is not a complete listing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
02c4a6acca
commit
4e94bb75aa
1 changed files with 49 additions and 33 deletions
|
|
@ -9,45 +9,60 @@ browser's localStorage.
|
|||
|
||||
## How a browser reaches a game
|
||||
|
||||
Browsers cannot open raw TCP, so the client never talks to `netmux`
|
||||
directly. Both of its transports go through **Hydra**, the connection
|
||||
proxy in [`mux/proxy`](../../mux/proxy), deployed alongside the game:
|
||||
Browsers cannot open raw TCP, but they do not need a middlebox either:
|
||||
**netmux serves WebSocket natively on its ordinary game ports**
|
||||
(`mux/src/websocket.cpp`, RFC 6455). A port is shared between telnet
|
||||
and WebSocket by first-byte protocol detection: a WebSocket client
|
||||
sends its HTTP `GET` immediately and is upgraded (`/wsclient` and `/`
|
||||
are both accepted); a classic telnet client waits for the server to
|
||||
speak and receives the banner after the `proto_detect_window` grace
|
||||
period (#1074/#2193 — runtime-settable, `0` disables detection for a
|
||||
telnet-only port). This works on plain and TLS ports alike, so `wss:`
|
||||
direct to the game is a two-line config away.
|
||||
|
||||
```
|
||||
browser ── ws(s) / gRPC-Web ──> hydra ── telnet TCP ──> netmux
|
||||
browser ── ws(s) ─────────────────> netmux game port (shared with telnet)
|
||||
browser ── ws(s) / gRPC-Web ──> hydra ── telnet ──> netmux
|
||||
```
|
||||
|
||||
- **Telnet over WebSocket** (`js/connection.js`) — the simple path.
|
||||
Point the client at a Hydra `websocket` / `websocket+tls` listener and
|
||||
bytes flow as-is; the client's own telnet engine (`js/telnet.js`)
|
||||
handles negotiation, `IAC GA` prompts, NAWS, TTYPE, and CHARSET.
|
||||
Any other telnet-over-WebSocket bridge works here too; nothing in
|
||||
this path is Hydra-specific.
|
||||
- **Telnet over WebSocket** (`js/connection.js`) — the simple path,
|
||||
and the direct one. Point the client at the game port (or at a
|
||||
Hydra `websocket` listener, or any generic telnet-over-WebSocket
|
||||
bridge — nothing in this path cares which) and bytes flow as-is; the
|
||||
client's own telnet engine (`js/telnet.js`) handles negotiation,
|
||||
`IAC GA` prompts, NAWS, TTYPE, and CHARSET.
|
||||
|
||||
- **Hydra GameSession** (`js/hydra_connection.js`) — the full protocol:
|
||||
protobuf `ClientMessage`/`ServerMessage` over a WebSocket with the
|
||||
`hydra-gamesession` subprotocol, falling back to gRPC-Web
|
||||
unary/streaming where WebSocket is blocked. This is what the
|
||||
`/hconnect`, `/hswitch`, `/hlinks`, `/hgames`, `/hscroll` commands
|
||||
drive (`/hhelp` lists them): multiple game links in one session,
|
||||
server-side scrollback fetch, and Hydra-stored credentials with
|
||||
auto-login. Session resume means a dropped browser connection picks
|
||||
up where it left off — the proxy holds the game link open.
|
||||
- **Hydra GameSession** (`js/hydra_connection.js`) — the optional
|
||||
richer protocol, via **Hydra**, the connection proxy in
|
||||
[`mux/proxy`](../../mux/proxy): protobuf `ClientMessage`/
|
||||
`ServerMessage` over a WebSocket with the `hydra-gamesession`
|
||||
subprotocol, falling back to gRPC-Web unary/streaming where
|
||||
WebSocket is blocked. This is what the `/hconnect`, `/hswitch`,
|
||||
`/hlinks`, `/hgames`, `/hscroll` commands drive (`/hhelp` lists
|
||||
them): multiple game links in one session, server-side scrollback
|
||||
fetch, and Hydra-stored credentials with auto-login. Session resume
|
||||
means a dropped browser connection picks up where it left off — the
|
||||
proxy holds the game link open across it, which the direct path
|
||||
cannot do.
|
||||
|
||||
## Deploying
|
||||
|
||||
1. Build and run Hydra next to the game: `cd mux/proxy && make`, copy
|
||||
`hydra.conf.example` to `hydra.conf`, and enable the listeners you
|
||||
want. See that file for TLS certificates, the master key that
|
||||
encrypts stored credentials, and health-check endpoints.
|
||||
2. Serve this directory from any static host — nginx, a CDN, an S3
|
||||
The minimal deployment is netmux plus static files — no extra process:
|
||||
|
||||
1. Serve this directory from any static host — nginx, a CDN, an S3
|
||||
bucket. There is nothing to compile.
|
||||
3. Two cross-origin rules to respect:
|
||||
- A page served over `https` may only open `wss:`/`https:`
|
||||
transports (mixed-content rule), so front the Hydra listeners with
|
||||
TLS in any real deployment.
|
||||
- gRPC-Web listeners deny cross-origin requests by default; add your
|
||||
client's origin with `cors_origin` in `hydra.conf`.
|
||||
2. Point the client at the game's host and port. A page served over
|
||||
`https` may only open `wss:` (mixed-content rule), so use a TLS
|
||||
game port for any real deployment.
|
||||
|
||||
Add Hydra when you want what the proxy provides — session resume,
|
||||
multi-game links, stored credentials, gRPC-Web for WebSocket-hostile
|
||||
networks: `cd mux/proxy && make`, copy `hydra.conf.example` to
|
||||
`hydra.conf`, and enable the listeners you want. See that file for
|
||||
TLS certificates, the master key that encrypts stored credentials,
|
||||
health-check endpoints, and `cors_origin` (gRPC-Web listeners deny
|
||||
cross-origin requests by default; plain WebSocket is not subject to
|
||||
CORS).
|
||||
|
||||
## Development
|
||||
|
||||
|
|
@ -66,6 +81,7 @@ it stays testable this way.
|
|||
|
||||
## Status
|
||||
|
||||
Part of the 2.14 development tree. The released 2.13 server has no
|
||||
Hydra, so a 2.13 game wanting browser play needs a generic
|
||||
telnet-over-WebSocket bridge and the simple transport above.
|
||||
Part of the 2.14 development tree. The released 2.13 server has
|
||||
neither the WebSocket listener nor Hydra, so a 2.13 game wanting
|
||||
browser play needs a generic telnet-over-WebSocket bridge and the
|
||||
simple transport above.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue