a websocket byte relay onto x11vnc's tcp socket, the same shape as the terminal's relay onto the pty sidecar. this is the piece plugins/desktop could not have: a plugin cannot claim a websocket provider. the rfb client is ours rather than vendored novnc — raw and copyrect, one pixel format we dictate so a rectangle memcpys into ImageData. we control the server, so the other eight encodings are surface we would carry and never run. execution, so owner-only: wine runs as the owner, which makes the game's menus file dialogs over the owner's home. two bugs worth keeping. the token key is BEARER_TOKEN, not token, so the upgrade 401'd before any rfb byte moved. and the /status health check opened a tcp connection to prove liveness — libvncserver blocks its accept loop peeking for a websocket handshake, so a polled health check filled the backlog and locked out the real viewer. a liveness check must not be indistinguishable from a client; it reads /proc/net/tcp now. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
21 lines
1.0 KiB
TypeScript
21 lines
1.0 KiB
TypeScript
import type { LayoutNode } from 'officerdev';
|
|
import { WorkspaceView } from 'officerdev';
|
|
import { useDashboardState } from 'state/useDashboardState';
|
|
import { defaultLayout } from './defaultLayout';
|
|
|
|
// /minesweeper — Minesweeper X running under wine on a virtual display, streamed over RFB.
|
|
//
|
|
// The pixels arrive through /api/minesweeper/ws, which is a byte relay onto x11vnc's own TCP socket on
|
|
// loopback — the same shape as the terminal's relay onto the pty sidecar, and the reason this works at
|
|
// all where `plugins/desktop` could not: a websocket provider is a platform concern, and a plugin
|
|
// cannot claim one.
|
|
//
|
|
// Owner-only, and not because a game is dangerous: wine runs as the server owner, so the game's menus
|
|
// are file dialogs with the owner's home behind them.
|
|
|
|
export const MinesweeperScreen = () => {
|
|
const workspace = useDashboardState<LayoutNode>('screens/minesweeper', defaultLayout);
|
|
|
|
return <WorkspaceView workspace={workspace} locked appTypes={{ allowed: ['minesweeper'], fallback: 'minesweeper' }} />;
|
|
};
|