Skip to main content

Module stdio

Module stdio 

Source
Expand description

What wraps rmcp’s stdio transport: a frame bound (BoundedLines) and a server/discover answer (DiscoverAnswering).

rmcp’s AsyncRwTransport reads a newline-delimited frame with read_until(b'\n', &mut self.line_buf) into a Vec<u8> it never bounds, so a peer that writes bytes and no \n grows that buffer until the allocator gives up (#234). HTTP has the derived POST cap and a 413; stdio had nothing.

BoundedLines is that missing half: an AsyncRead wrapper that counts the bytes since the last \n and fails the read past the cap. The obvious alternatives do not work — JsonRpcMessageCodec’s new_with_max_length bounds only the FramedWrite half, which is bugwarden’s own output, and AsyncReadExt::take truncates the whole stream rather than one frame.

An over-cap frame is fatal, not skippable: the request id lives inside the unparsed frame, so no response can name it, and rmcp clients set no default request timeout — a peer that resumed would hang forever, which is worse than a closed transport. rmcp maps the read error to receive() -> None, i.e. a silent close indistinguishable from a clean peer hangup, so the trip is also published through BoundedLines::over_cap for main to turn into a non-zero exit.

DiscoverAnswering is the other half: rmcp reads the stdio lifecycle off the first frame, so a server/discover probe committed the session to the handshake-free lifecycle before it was answered (#267). Both are transport-level because both are: the frame never reaches a handler.

Structs§

BoundedLines
An AsyncRead that fails once a newline-delimited frame exceeds cap bytes.
DiscoverAnswering
A Transport that answers server/discover itself and hands rmcp every other frame untouched.