Packet Framing — Magic Terminator
This short note explains how packets are framed and reassembled in the network packages, at a logical level. The framing strategy is simple and robust to transport fragmentation or aggregation.
Concept
Each logical packet is a payload of bytes that the application wants to send (JSON or binary).
Before sending, the library appends a configurable terminator string (the “magic value”) to the end of the payload. The default value in the project config is PACKET_END.
The terminator is applied as bytes (UTF-8 encoding of the configured string) and therefore forms a unique byte suffix that marks the end of a logical packet.
Why an end terminator
Transports like WebSocket and RTC DataChannels may split or combine application messages into arbitrary chunks. A terminator lets a receiver reliably detect the end of each logical packet regardless of how the transport fragments or aggregates bytes.
Using a short, human-readable terminator makes debugging easier.
The terminator is configurable so you can pick a value that does not collide with your payload contents (especially important if using raw or binary payloads).
Sender logic
Serialize the application message into bytes (e.g., JSON => UTF-8 bytes, or a binary codec output).
Append the configured terminator bytes to the end of the payload.
Send the resulting buffer on the transport (WebSocket or DataChannel).
Receiver logic
Accumulate incoming chunks of bytes into a per-connection buffer.
Repeatedly search the accumulated buffer for the terminator sequence.
For each occurrence, extract bytes from buffer start up to (but not including) the terminator — this is a complete logical packet.
Remove the extracted packet and trailing terminator from the buffer and continue searching; keep any leftover bytes (partial packet) for the next incoming chunk.