feat(ctrl): add control stream frame codec

Add the framing layer that turns typed control messages into bytes for reliable
QUIC streams. This keeps the codec next to the control schema while leaving the
actual QUIC read/write loops for a later relay/client/gateway slice.

The codec uses a four-byte big-endian length prefix followed by JSON. JSON is a
phase-1 choice for inspectability during manual tunnel bring-up; the explicit
length prefix keeps stream parsing deterministic and the 64 KiB cap prevents a
peer from announcing unbounded control payloads. Decoding validates the message
after deserialization so forged stream bytes cannot bypass constructor checks.

The next networking slice can use complete_control_frame_len to split a stream
buffer and decode_control_frame once a complete frame is available.

Test Plan:
- cargo fmt --check
- cargo test --workspace
- cargo clippy --workspace --all-targets -- -D warnings

Refs: PLAN.md reliable QUIC control stream requirements
This commit is contained in:
2026-05-21 17:25:26 +02:00
parent d1e6530829
commit 879cb689a4
6 changed files with 244 additions and 3 deletions
+9 -3
View File
@@ -1,11 +1,17 @@
//! Reliable control-plane messages for the LAN party tunnel.
//!
//! QUIC streams will carry these messages. The crate does not choose a stream
//! codec yet; it defines the typed handshake and status model that client,
//! relay, and gateway must validate consistently.
//! QUIC streams carry these messages as length-prefixed JSON frames. The crate
//! defines the typed handshake/status model and the small framing layer needed
//! by client, relay, and gateway stream handlers.
use std::{fmt, str::FromStr};
mod codec;
pub use codec::{
CONTROL_LENGTH_PREFIX_LEN, ControlCodecError, MAX_CONTROL_MESSAGE_LEN,
complete_control_frame_len, decode_control_frame, encode_control_message,
};
pub use lanparty_obs::TunnelStats;
use lanparty_proto::{MIN_USEFUL_TAP_MTU, MacAddr, MtuError, recommended_tap_mtu};
use thiserror::Error;