decode
Parse ONE already-deframed message body: the 4-byte length prefix has been stripped, so frame is [id][payload...] (length >= 1 for a real message). An empty frame is a keep-alive (the caller saw length == 0).
Mirrors the per-type on_* parsers and the dispatch_message switch. Frames that are too short for their declared type fall through to Unknown rather than throwing, so a caller looping over a buffer never crashes on a peer that sends a malformed body. The connection layer decides whether to disconnect.