- Add VfsFile: Send supertrait for Mutex compatibility - Fix SmbServerCommand: struct → Subcommand enum with Start variant - Fix tracing_subscriber::init() → try_init() to avoid panic when logger already initialized - Fix CLI subcommand name: smb-server → smb-start (flatten naming) - Add #[command(name = "smb-start")] for CLI disambiguation - Fix unused variable warnings (smb_fs.rs, smb_server_backend.rs) - Remove unused VfsFile imports (webdav.rs, scp_handler.rs) - Integration test: Docker smbclient verified (list, upload, read)
2.2 KiB
2.2 KiB
Pack -- binary serialization primitives
Cursor-based binary reader/writer for SMB2 wire format. Hand-rolled, no proc macros.
Key files
| File | Purpose |
|---|---|
mod.rs |
ReadCursor, WriteCursor, Pack/Unpack traits, primitive read/write methods |
guid.rs |
GUID pack/unpack with mixed-endian layout |
filetime.rs |
Windows FILETIME (100ns ticks since 1601-01-01) to/from SystemTime |
Core types
ReadCursor<'a>: Reads from&[u8]with position tracking. ReturnsErroron buffer overrun (no panics). All reads are little-endian.WriteCursor: Writes into a growableVec<u8>. Supports backpatching (set_u16_le_at,set_u32_le_at) for length fields written before their values are known.align_to(n)pads with zeros to n-byte boundary.Packtrait:fn pack(&self, cursor: &mut WriteCursor)-- serialize to binary.Unpacktrait:fn unpack(cursor: &mut ReadCursor) -> Result<Self>-- deserialize from binary.
GUID mixed-endian layout
Windows GUIDs have a mixed-endian wire format:
data1(u32): little-endiandata2(u16): little-endiandata3(u16): little-endiandata4([u8; 8]): raw bytes (no endian conversion)
This matches the COM/DCOM convention. Not the same as RFC 4122 UUID byte order.
FileTime conversion
Windows FILETIME: 100-nanosecond intervals since 1601-01-01 00:00:00 UTC. Unix epoch: 1970-01-01 00:00:00 UTC. Offset: 11,644,473,600 seconds (116,444,736,000,000,000 ticks).
Key decisions
- Hand-rolled instead of proc macros: Full control over wire format details (offsets, alignment, backpatching). Easier to debug. No build-time dependency.
MAX_UNPACK_BUFFER(16 MB):read_bytes_boundedrefuses allocations larger than 16 MB. Prevents OOM from malicious packets claiming huge lengths.
Gotchas
- Everything is little-endian: Except TCP framing (see transport module). ReadCursor/WriteCursor only do LE.
- UTF-16LE byte length must be even:
read_utf16_lereturns an error on odd byte counts. - Backpatching requires placeholder: Write a zero first, then
set_u32_le_atto overwrite once the real value is known. Common pattern for length-prefixed fields.