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§
- Bounded
Lines - An
AsyncReadthat fails once a newline-delimited frame exceedscapbytes. - Discover
Answering - A
Transportthat answersserver/discoveritself and hands rmcp every other frame untouched.