add payload_len field to wire protocol header

Ethernet pads frames to 60 bytes minimum; without an explicit length
field the receiver cannot distinguish real payload from zero padding
(e.g. a 6-byte DISCOVER becomes 46 bytes after padding, failing the
'payload must be empty' check).

Header is now 8 bytes: [ver:1][type:1][session_id:4][payload_len:2]
(both multi-byte fields big-endian). The receiver slices exactly
payload_len bytes and ignores trailing padding.

Updated PROTOCOL.md, Rust frame.rs, and C# Frame.cs.
This commit is contained in:
2026-08-13 07:51:39 +00:00
parent dc5df5c073
commit f09028b135
3 changed files with 78 additions and 57 deletions
+11 -5
View File
@@ -11,7 +11,9 @@ discriminator; there is no magic number inside the payload.
+---------------+---------------+-------------------------------+
| version | type | session_id |
+---------------+---------------+-------------------------------+
| payload ... |
| payload_len (big-endian) | payload ... |
+-------------------------------+ +
| |
+---------------------------------------------------------------+
```
@@ -19,15 +21,19 @@ discriminator; there is no magic number inside the payload.
- **type** (u8): frame type, see table below.
- **session_id** (u32, big-endian): `0` for non-session frames; the
server-assigned ID for session-scoped frames.
- **payload** (variable): type-dependent. No length field is carried — the
Ethernet frame length from the capture gives the payload extent.
- **payload_len** (u16, big-endian): number of payload bytes that follow.
The receiver reads exactly this many bytes and ignores any trailing
Ethernet padding (frames under 60 bytes are zero-padded by the NIC to
meet the minimum Ethernet frame size).
- **payload** (`payload_len` bytes): type-dependent.
No CRC, no retransmit, no ordering at this layer. TCP reliability is handled by
the endpoints' TCP stacks; UDP (reserved) will rely on application-level
mechanisms.
Maximum payload: 1500 (Ethernet MTU) 14 (eth header) 6 (our header) =
**1480 bytes**. Larger payloads are not emitted in v1.
Maximum payload: 1500 (Ethernet MTU) 8 (our header) = **1492 bytes**. In
practice we cap at **1480** to stay conservative. Larger payloads are not
emitted in v1.
## Frame types