Table of Contents
Fragmentation
MOSH fragmentation allows a logical message payload to be larger than a single on-wire frame.
Why Fragmentation Exists
The MOSH protocol standard limits the maximum encoded frame size to 1470 bytes. That full frame includes:
- 13-byte fixed header
- payload
- 2-byte CRC footer
That means the largest unfragmented payload is:
1470 - 13 - 2 = 1455 bytes
Any payload larger than 1455 bytes must be split into multiple fragment frames before transmission.
Fragment Format
A fragment is still a normal MOSH frame, but it has the `FLAG_IS_FRAGMENT` bit set and uses the first 4 bytes of its payload as a fragment header:
- byte 0: fragment index
- byte 1: fragment count
- byte 2: original payload length, low byte
- byte 3: original payload length, high byte
The remaining payload bytes in the fragment are fragment data.
For a transport with a 1470-byte frame limit:
- max frame size: 1470
- fixed header: 13
- footer: 2
- payload area per fragment: 1455
- fragment header: 4
- usable data per fragment: 1451
Send Path
When a frame is sent, MOSH first checks whether the encoded frame would exceed the transport's maximum frame length.
If it fits:
- the frame is sent as-is
If it does not fit:
- the payload is split into multiple fragments
- each fragment gets the same message ID, source, destination, context, and TTL
- the fragment flag is set
- each fragment carries part of the original payload
This means a large logical payload is transmitted as a sequence of smaller wire-safe frames.
Receive Path
On receipt, each frame is decoded normally.
If the fragment flag is not set:
- the frame is delivered immediately
If the fragment flag is set:
- the fragment is stored in a reassembly buffer
- fragments are grouped by source network ID, source node ID, and message ID
- once all fragments are present, the original payload is rebuilt in fragment-index order
- the fragment flag is cleared
- the completed frame is delivered as a normal logical frame
Reassembly Rules
A fragment set is considered valid only if:
- fragment count is not zero
- fragment index is less than fragment count
- all fragments agree on the original payload length
- the total reassembled payload length matches the declared original length
If the fragment metadata changes mid-stream, or the final payload length does not match, the reassembly buffer is discarded.
Limits
There are two important limits:
- Wire frame limit: 1470 bytes maximum encoded frame size
- Logical payload limit: up to 65535 bytes, because original payload length is stored as a 16-bit value in the fragment header
In practice, the true upper limit is also constrained by available RAM, especially on embedded devices such as the ESP32.
Current Behavior
On the current MOSH implementation:
- large logical payloads are fragmented automatically before send
- received fragments are reassembled automatically
- completed frames are exposed to higher-level code as normal non-fragmented logical frames
As a result, application code can work with large payloads without needing to manually split or reassemble them.
