aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/protocol.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/protocol.ts')
-rw-r--r--src/daemon/protocol.ts58
1 files changed, 2 insertions, 56 deletions
diff --git a/src/daemon/protocol.ts b/src/daemon/protocol.ts
index 997a6c8..d3d8297 100644
--- a/src/daemon/protocol.ts
+++ b/src/daemon/protocol.ts
@@ -1,34 +1,17 @@
-/**
- * Unix socket daemon protocol — wire message types, type guards, and constants.
- *
- * The daemon speaks JSON-line protocol over a Unix domain socket.
- * One JSON object per newline. Four message types: request, response, event, control.
- *
- * References:
- * - CDP message format: https://github.com/aslushnikov/getting-started-with-cdp#protocol-fundamentals
- * - net.createServer IPC: https://nodejs.org/docs/latest-v22.x/api/net.html#serverlistenpath-backlog-callback
- * - readline line-delimited: https://nodejs.org/docs/latest-v22.x/api/readline.html#event-line
- */
import { isRecord } from "../util/guards";
-// ── Message types ──────────────────────────────────────────────────────────────
-/** A CDP command sent from a pi client to the daemon. */
export type WireRequest = {
readonly type: "request";
- /** Client-local CDP id. The daemon remaps this to a globally-unique id for Chrome. */
readonly id: number;
readonly method: string;
readonly params?: Record<string, unknown>;
- /** Optional CDP session id. Omitted for browser-level commands. */
readonly sessionId?: string;
};
-/** A CDP response (result or error) sent from the daemon back to the pi client. */
export type WireResponse = {
readonly type: "response";
- /** Matches the id from the corresponding WireRequest. */
readonly id: number;
readonly result?: unknown;
readonly error?: {
@@ -38,34 +21,23 @@ export type WireResponse = {
};
};
-/** A CDP event forwarded from Chrome through the daemon to pi client(s). */
export type WireEvent = {
readonly type: "event";
readonly method: string;
readonly params?: Record<string, unknown>;
- /** Session-scoped events carry this; browser-level events omit it. */
readonly sessionId?: string;
};
-/** Daemon lifecycle control messages. Bidirectional. */
export type WireControl = {
readonly type: "control";
readonly action: "register" | "registered" | "deregister" | "shutdown";
- /** pi client namespace (required for register/registered/deregister). */
readonly clientId?: string;
- /** Human-readable reason for shutdown. */
readonly reason?: string;
};
-/** All messages that may appear on the Unix socket. */
export type WireMessage = WireRequest | WireResponse | WireEvent | WireControl;
-// ── Type guard ─────────────────────────────────────────────────────────────────
-/**
- * Validates that an unknown parsed-JSON value is a well-formed WireMessage.
- * Does NOT validate the full CDP semantics — only structural shape.
- */
export const isWireMessage = (v: unknown): v is WireMessage => {
if (!isRecord(v)) return false;
const t = v["type"];
@@ -113,12 +85,9 @@ export const isWireMessage = (v: unknown): v is WireMessage => {
}
};
-// ── Wire message constructors ──────────────────────────────────────────────────
-/** Serialize a WireMessage to a JSON line (no trailing newline — caller adds \\n). */
export const serialize = (msg: WireMessage): string => JSON.stringify(msg);
-/** Deserialize a single JSON-line string to a WireMessage. Returns null on parse failure. */
export const deserialize = (line: string): WireMessage | null => {
let parsed: unknown;
try {
@@ -130,42 +99,19 @@ export const deserialize = (line: string): WireMessage | null => {
return parsed;
};
-// ── Constants ──────────────────────────────────────────────────────────────────
-/**
- * IPC endpoint for the daemon.
- *
- * On POSIX platforms this is a Unix domain socket path. On Windows, Node's IPC
- * requires a named pipe of the form `\\.\pipe\<name>` — a Unix path like
- * `/tmp/…` is not a valid `net` listen/connect target there and causes setup
- * to fail. See https://nodejs.org/api/net.html#ipc-support.
- */
+// Windows requires a named pipe (`\\.\pipe\<name>`); a Unix path is not a valid `net` listen/connect target there.
export const DAEMON_SOCKET_PATH =
process.platform === "win32"
? "\\\\.\\pipe\\pi-browser-daemon"
: "/tmp/pi-browser-daemon.sock";
-/**
- * How long the daemon stays alive with zero connected clients before exiting
- * (milliseconds). After this period, the daemon cleans up and shuts down.
- */
-export const DAEMON_IDLE_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
+export const DAEMON_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
-/**
- * Hard cap on concurrent pi client connections. Extra connections are rejected
- * immediately to prevent resource exhaustion.
- */
export const DAEMON_MAX_CLIENTS = 16;
-/**
- * If true, the daemon unlinks (deletes) any stale socket file from a previous
- * daemon crash before calling server.listen(). Without this, a crashed daemon
- * leaves a socket inode that blocks the next listen() call with EADDRINUSE.
- */
export const DAEMON_STALE_SOCKET_CLEANUP = true;
-/** CDP WebSocket connection timeout (ms). */
export const CDP_CONNECT_TIMEOUT_MS = 10_000;
-/** CDP command timeout when proxying through daemon (ms). */
export const CDP_COMMAND_TIMEOUT_MS = 10_000;