You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(ocap-kernel): use length-prefixed framing for remote messages (#957)
## Summary
- Remote messages larger than `@libp2p/webrtc`'s 16 KB
`MAX_MESSAGE_SIZE`
were being split into multiple datachannel sends, but the kernel was
reading from a `byteStream` that doesn't preserve message boundaries.
The reader would wake on the first chunk and call `JSON.parse` on a
truncated string; the parse error was caught silently, no ACK was sent,
and the sender's `RemoteHandle` retried until `MAX_RETRIES` was hit and
it gave up.
- Switched to `lpStream` (length-prefixed framing) so each `write()`
produces exactly one `read()` regardless of how the underlying webRTC
transport chunks the bytes on the wire.
- Set `maxDataLength = DEFAULT_MAX_MESSAGE_SIZE_BYTES` (1 MB) on the
receiver so the new framing's size cap matches the sender-side
`validateMessageSize` policy.
- Translated `InvalidDataLengthError` / `InvalidDataLengthLengthError`
from `lpStream` into a `ResourceLimitError` with
`limitType: 'messageSize'`, so size-related failures look the same
whether they tripped on the sender or the receiver.
- Caught `UnexpectedEOFError` in the read loop and treated it as a
graceful stream end (the byteStream's old `null`-return path is gone
with lpStream).
## Test plan
- [x] `yarn workspace @MetaMask/ocap-kernel test:dev:quiet` — all 2341
unit tests pass
- [x] `yarn workspace @MetaMask/ocap-kernel build` — clean
- [x] `yarn workspace @MetaMask/ocap-kernel lint:fix` — clean
- [x] End-to-end: ran the orchestration demo through to the Sales phase,
with the schematic-generation service (~17 KB SVG payload) and
pcb-layout service (~15 KB SVG) both delivering successfully where
they were timing out before.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: packages/ocap-kernel/CHANGELOG.md
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -41,6 +41,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
41
41
- Regenerate `incarnationId` when `resetStorage=true` clears the rest of kernel state, completing the #948 peer-restart detection on browser/extension kernel reloads ([#950](https://github.com/MetaMask/ocap-kernel/pull/950))
42
42
- The previous except-list preserved `incarnationId` across `resetStorage` wipes, so a restarted sender signalled the same incarnation it had before the wipe and the matching receiver's handshake decided "no restart" — leaving stale `highestReceivedSeq` in place and silently dropping the sender's fresh `seq=1` messages
43
43
- Register a new vat with its subcluster before awaiting `runVat`, so a garbage-collection pass during bundle load cannot delete the still-empty subcluster out from under the in-progress vat creation ([#952](https://github.com/MetaMask/ocap-kernel/pull/952))
44
+
- Use length-prefixed framing for remote messages so payloads larger than the underlying transport's per-frame cutoff (e.g. `@libp2p/webrtc`'s 16 KB datachannel limit) are reassembled correctly on the receiver ([#957](https://github.com/MetaMask/ocap-kernel/pull/957))
45
+
- Replace `byteStream` with `lpStream` on every remote channel; the byte-oriented stream did not preserve `write()` boundaries, so any message the transport split into multiple frames was parsed from the first frame only, silently dropped without acknowledgement, and the sender retried until giving up after `MAX_RETRIES`
46
+
- Surface receiver-side framing-cap violations (`InvalidDataLengthError`, `InvalidDataLengthLengthError`) as `ResourceLimitError` with `limitType: 'messageSize'` so size errors look the same whether they tripped on the sender's `validateMessageSize` or the receiver's framing decoder
0 commit comments