Skip to content

Commit f1563f5

Browse files
rustyconoverclaude
andcommitted
feat: raw-TCP socket transport (serveTcp / tcpConnect / TransportKind.TCP)
Add a TCP (AF_INET) transport that speaks the raw Arrow-IPC framing protocol — the network analog of the existing AF_UNIX runner, for trusted-network co-located workers that want the lean framing without the HTTP envelope. Mirrors the Python reference (vgi-rpc 8ea49aa). - src/launcher/serve-tcp.ts: serveTcp(protocol, { host, port, ... }) binds (host, port), defaults host to 127.0.0.1 (loopback only), port 0 lets the OS auto-select, disables Nagle (setNoDelay) per connection, and emits a TCP:<host>:<port> discovery line once bound (after which no more stdout). Same per-connection IPC dispatch loop and idle-timeout model as serveUnix. - src/client/tcp.ts: tcpConnect(host, port) client helper wrapping pipeConnect over a connected TCP socket. Node-only (statically imports node:net), so it is exported only from the node barrel, never from the runtime-agnostic core that browser/workerd bundles re-export. - TransportKind.TCP; serveTcp reports it via the ServeStartHook / DispatchInfo. - examples/conformance.ts: --tcp [HOST:]PORT (loopback-default host), prints TCP:<host>:<port> — mirrors the --unix / UNIX:<path> launcher contract. - Focused round-trip tests (test/tcp.test.ts) and rebuilt dist. Raw TCP carries NO authentication or TLS; it is for trusted networks only and defaults to loopback (127.0.0.1). Use the HTTP transport for untrusted networks. Verified cross-language: TS --tcp worker against `vgi-rpc-test --tcp` passes 102 total / 98 passed / 0 failed / 4 skipped — exact parity with the pipe run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 0d49a69 commit f1563f5

26 files changed

Lines changed: 2237 additions & 1282 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Define RPC methods with Arrow-typed schemas, serve them over stdin/stdout, and i
1616
- **Runtime introspection** — opt-in `__describe__` method for dynamic service discovery via the CLI
1717
- **Result validation** — missing required fields in handler results throw descriptive errors at emit time
1818
- **Authentication** — bearer tokens, JWT, mTLS (PEM-in-header and XFCC), with chainable authenticators
19-
- **Three client transports** — HTTP, subprocess, and raw pipe, all sharing a unified `RpcClient` interface
19+
- **Four client transports** — HTTP, subprocess, raw pipe, and raw TCP (`tcpConnect` / `serveTcp`), all sharing a unified `RpcClient` interface. Raw TCP carries no auth/TLS and defaults to loopback (`127.0.0.1`) — trusted networks only; use HTTP otherwise.
2020

2121
## Installation
2222

dist/client/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ export type { OAuthResourceMetadataResponse } from "./oauth.js";
44
export { fetchOAuthMetadata, httpOAuthMetadata, parseClientId, parseClientSecret, parseDeviceCodeClientId, parseDeviceCodeClientSecret, parseResourceMetadataUrl, parseUseIdTokenAsBearer, } from "./oauth.js";
55
export { PipeStreamSession, pipeConnect, subprocessConnect } from "./pipe.js";
66
export { HttpStreamSession } from "./stream.js";
7-
export type { HttpConnectOptions, LogMessage, PipeConnectOptions, StreamSession, SubprocessConnectOptions, } from "./types.js";
7+
export type { HttpConnectOptions, LogMessage, PipeConnectOptions, StreamSession, SubprocessConnectOptions, TcpConnectOptions, } from "./types.js";
88
//# sourceMappingURL=index.d.ts.map

dist/client/index.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/client/tcp.d.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { RpcClient } from "./connect.js";
2+
import type { TcpConnectOptions } from "./types.js";
3+
/**
4+
* Connect to a vgi-rpc server over a raw TCP socket and wrap it with
5+
* {@link pipeConnect}. The network analog of `subprocessConnect`: identical
6+
* lockstep raw Arrow-IPC framing, only the transport differs. Nagle's
7+
* algorithm is disabled (`setNoDelay(true)`) so lockstep requests are not
8+
* delayed coalescing writes. The returned client's {@link RpcClient.close}
9+
* also destroys the socket.
10+
*
11+
* SECURITY: raw TCP carries **no authentication or TLS** — only connect to
12+
* trusted endpoints. Use `httpConnect` for untrusted networks.
13+
*
14+
* @param host Hostname or IP address of the TCP server.
15+
* @param port TCP port of the server.
16+
* @param options Optional log/external-location configuration.
17+
*/
18+
export declare function tcpConnect(host: string, port: number, options?: TcpConnectOptions): RpcClient;
19+
//# sourceMappingURL=tcp.d.ts.map

dist/client/tcp.d.ts.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/client/types.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ export interface PipeConnectOptions {
4242
/** External storage config for resolving externalized batches. */
4343
externalLocation?: import("../external.js").ExternalLocationConfig;
4444
}
45+
/**
46+
* Options for {@link tcpConnect}, the raw-TCP-socket RPC client.
47+
*
48+
* SECURITY: raw TCP carries no authentication or TLS — connect only to
49+
* trusted endpoints (use {@link httpConnect} for untrusted networks).
50+
*/
51+
export interface TcpConnectOptions extends PipeConnectOptions {
52+
}
4553
/** Options for {@link subprocessConnect}, which spawns a server process and pipes to it. */
4654
export interface SubprocessConnectOptions extends PipeConnectOptions {
4755
/** Working directory for the spawned process. Defaults to the current directory. */

dist/client/types.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export { tcpConnect } from "./client/tcp.js";
12
export * from "./index.core.js";
2-
export { acquireLock, computeHash as launcherComputeHash, defaultStateDir, type FileLockHandle, type GcResult, gcStateDir, type LaunchConfig, launch, probeSocket, type ServeUnixHandle, type ServeUnixOptions, type SocketPaths, type StatusRow, serveUnix, socketPaths, statusRows, tryAcquireLock, } from "./launcher/index.js";
3+
export { acquireLock, computeHash as launcherComputeHash, defaultStateDir, type FileLockHandle, type GcResult, gcStateDir, type LaunchConfig, launch, probeSocket, type ServeTcpHandle, type ServeTcpOptions, type ServeUnixHandle, type ServeUnixOptions, type SocketPaths, type StatusRow, serveTcp, serveUnix, socketPaths, statusRows, tryAcquireLock, } from "./launcher/index.js";
34
//# sourceMappingURL=index.d.ts.map

dist/index.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)