====== 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.