4.5 KiB
4.5 KiB
id, name, status, depends_on, scope, risk, impact, level, tags
| id | name | status | depends_on | scope | risk | impact | level | tags | ||
|---|---|---|---|---|---|---|---|---|---|---|
| review-001-ws-pump-consolidation | Dedupe pumps + byte-based caps + write-side validation (WS-11, WS-04, WS-05, WS-06, HY-09) | completed | moderate | medium | component | implementation |
|
Description
Review 001 findings where the correct fix is restructuring the duplicated
pump code in src/websocket/byte_adapter.rs, so they are done once
instead of twice (axum path :119-180, tungstenite twin :299-364):
- WS-11: ~60 lines of pump logic (read task, write task, close handling) are copy-pasted between the axum and tungstenite paths while the module doc claims "one implementation, both directions". Factor over a generic sink/stream of messages. This also closes COV-03 (the tungstenite twins are untested).
- WS-04 + HY-09: the write-side chunk parser does no length
validation (
:161-163, twin:343-345) — non-chunk-framed bytes make the parser silently wait to accumulate8 + len(up to ~4 GiB) from misaligned offsets. Validatelen > MAX_CHUNK_LEN→ fail the stream loudly; saturating add for the 32-bit overflow. - WS-05: the write-side
pendingbuffer is bounded in slots (64) but not in bytes (~1 GiB worst case per connection with a slow sink). Cappendinggrowth in bytes. - WS-06: inbound per-connection memory bound is 64 slots × 64 MiB
(axum/tungstenite defaults) ≈ 4 GiB —
max_message_size/max_frame_sizeare never configured. Set explicit caps consistent with the plan's ~1 MiB write-side intent.
Acceptance Criteria
- Pump bodies factored into one generic implementation (both paths share it)
- Write-side rejects
len > MAX_CHUNK_LENwith a stream error (test); no8 + lenoverflow path - Write
pendingbyte-capped; inbound message/frame size explicitly configured (tests) - Tungstenite path exercised by the shared test suite (COV-03 backfilled)
- 16 MiB round-trip and disconnect-cleanup tests still pass
cargo testandcargo clippy --all-targets -- -D warningspass
References
- docs/reviews/001-initial-implementation-review.md (Part B, WS-04, WS-05, WS-06, WS-11; HY-09; COV-03)
Notes
Agent fills during implementation. Sequenced with (or after) review-001-ws-eof-signal so the dedup doesn't churn under it — both touch byte_adapter.rs.
Summary
Restructured src/websocket/byte_adapter.rs in three commits:
- WS-04/HY-09 (
5024d99): the write-side chunk parser validates the 8-byte header's length field against alkcall'sMAX_CHUNK_LEN(re-exported asalkhttp::websocket::MAX_CHUNK_LEN) with saturating8 + len. Oversized header → the pump closes the socket (1011) and signals theAsyncWritehalf through a one-shot error channel, sopoll_writefails loudly (InvalidData, "chunk length exceeds MAX_CHUNK_LEN") instead of silently waiting toward ~4 GiB. Tested on the tungstenite path over a raw duplex pair. - WS-05/WS-06 (
92cc11a):pendingis byte-capped atPENDING_BUFFER_CAP(=MAX_CHUNK_LEN + 8, checked pre-extend and post-parse; a smaller "e.g. 1 MiB" cap false-positives because the alkcall mux passes each payload up to 16 MiB as oneAsyncWritecall — the cap is the exact bound well-framed traffic can occupy). Both pumps fail loudly on breach. Inbound capsINBOUND_WS_MESSAGE_CAP/INBOUND_WS_FRAME_CAP(both 1 MiB) set on the axum upgrade (max_message_size/max_frame_size) and the tungstenite dial (connect_async_with_config+WebSocketConfig); frame cap = message cap because the path does not use WS fragmentation and tungstenite rejects a single oversize frame before reassembly. A read-task inbound error surfaces a 1011 close to the peer + stream error (tested). - WS-11/COV-03 (
1db0ea8+e9ddf94): one generic implementation ([WsFraming] trait +run_read_pump/run_write_pump) with two flavor impls (axum/tungstenite); the EOF watch mechanism,read_eofreceiver, and from_wss monitor unchanged. Six byte-adapter unit tests now exercise the tungstenite path directly (WS-04, WS-05, well-framed passthrough, binary read, EOF retention, text→1002); the shared ws_upgrade_session/ws_overlay_ops/from_wss suites cover both paths end-to-end.
Verification per commit: cargo test, cargo clippy --all-targets -- -D warnings; final also cargo test --all-features, cargo clippy --all-features --all-targets -- -D warnings, cargo fmt --check —
all green, including the 16 MiB round-trip and disconnect-cleanup
tests.