fix(stream-install)!: stream archive payloads as raw frames
Streamed installs were sending FileChunk payloads through the shared JSON Message impl. serde_json serializes bytes as arrays of integers, which bloats wire traffic and burns CPU on large archives. Replace StreamInstallFrame encoding with tagged frames: JSON control frames keep their shape under tag 0, while file chunks carry raw bytes under tag 1. The stream install metadata now carries unpacked archive size and mandatory CRC32. The CLI unrar provider validates CRCs up front, runs one archive-wide unrar p stream, splits stdout by listed file sizes, and refuses trailing or missing bytes. That avoids solid archive re-decompression and sidesteps unrar wildcard masks for path arguments. Receivers now sample existing download progress events for streamed installs, report staging-relative chunk paths, and retry trusted peers with a fresh streamed-install transaction after a failed attempt. The current protocol policy does not preserve compatibility with older stream-install builds. Test Plan: - just fmt - just test - just clippy - git diff --check - git diff --cached --check BREAKING CHANGE: StreamInstallFrame now uses tagged frames with raw chunk payloads and requires current peers on both sides of streamed installs. Refs: NEXT_STEPS_CLAUDES_REVIEW.md
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
use bytes::Bytes;
|
||||
use lanspread_proto::{Message, StreamInstallFrame};
|
||||
|
||||
#[test]
|
||||
fn file_chunks_encode_raw_bytes() {
|
||||
let bytes = Bytes::from_static(&[0, 1, 2, 255]);
|
||||
let encoded = StreamInstallFrame::FileChunk {
|
||||
bytes: bytes.clone(),
|
||||
}
|
||||
.encode();
|
||||
|
||||
assert_eq!(&encoded[..], &[1, 0, 1, 2, 255]);
|
||||
assert_eq!(
|
||||
StreamInstallFrame::decode(encoded),
|
||||
StreamInstallFrame::FileChunk { bytes }
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn control_frames_are_tagged_json() {
|
||||
let frame = StreamInstallFrame::FileBegin {
|
||||
relative_path: "bin/game.exe".to_string(),
|
||||
size: 42,
|
||||
crc32: 0x38B4_88A7,
|
||||
};
|
||||
let encoded = frame.encode();
|
||||
|
||||
assert_eq!(encoded[0], 0);
|
||||
assert_eq!(StreamInstallFrame::decode(encoded), frame);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_frames_decode_as_errors() {
|
||||
match StreamInstallFrame::decode(Bytes::new()) {
|
||||
StreamInstallFrame::Error { message } => {
|
||||
assert!(message.contains("empty"));
|
||||
}
|
||||
other => {
|
||||
panic!("expected error frame, got {other:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user