A repeater already relays every public-channel (GRP_TXT) flood packet that
passes through it. This keeps a bounded, in-RAM ring buffer of those packets so
a client that was out of range can pull back the messages it missed, using an
anonymous request (ANON_REQ sub-type 0x04) -- no login.
Design points:
- Repeater-only. Room server untouched.
- The repeater holds no channel key. Packets are cached and replayed still
channel-encrypted, so a non-member who asks receives ciphertext it cannot
read, and a member decrypts with the key it already has.
- Served directly to the requesting client, never re-flooded, so it adds no
broadcast airtime.
- No login: public channel data is not admin-only. Rate-limited by the existing
anon_limiter, like the other anonymous requests.
- Bounded RAM (32 entries, ~6 KB), nothing persisted -- a rotating cache in the
small internal-flash FS would be a wear anti-pattern.
- Channel broadcasts only, never direct messages, so this does not reintroduce
the ACK/timeout problem that closed#613.
The request params {channel_hash, since_ts, max_count} are optional and
self-describing via a leading length byte, so a stock client that sends only a
reply path gets sensible defaults. A plain length check cannot work here: the
ANON_REQ plaintext is zero-padded to the AES block size, so the decrypted
length exceeds what the sender wrote.
The reply is capped at 160 bytes. reply_data is MAX_PACKET_PAYLOAD (184), but
the binding limit is the companion's host serial frame -- {push code}{reserved}
{tag:4} plus the reply padded to the AES block size minus 4, against
MAX_FRAME_SIZE of 176. Larger replies are transmitted but dropped before the
app sees them. Clients page for the remainder with `since`.
ChannelHistory is a hardware-independent template, covered by 11 googletest
cases under a dedicated native env.