Name a COMPRESS mismatch instead of reporting an opaque decode failure - #10
Merged
Conversation
added 3 commits
September 3, 2026 23:15
Any read error that was not a timeout was answered "Failed to decode", so a broken connection looked to the sender like a malformed message. The protocol has no reply for a transport fault and the connection has already broken, so it is logged as itself and closed.
Compression is configuration at both ends and is deliberately not signalled on
the wire, so a mismatch could only ever appear as "Failed to decode" — the same
answer as a corrupt payload or malformed JSON, with nothing to say which.
The lz4 frame magic settles it in four bytes, so the daemon now says which end
is wrong:
payload is not an lz4 frame but COMPRESS is on: the sender is not
compressing. COMPRESS must match at both ends
The reply stays "Failed to decode", since the protocol's reply set is fixed. A
frame whose magic is intact but whose body is damaged is still reported as
corruption, not as a configuration error.
The resolver reads these refusals too, and is where an operator sees them
first, so it now logs what each one usually means. A test pins those hints to
the reply strings PROTOCOL.md documents, so advice cannot outlive its refusal.
The firewall names the direction in its own log, but an operator reads the
resolver's first. The resolver knows what it sent, which settles the direction
from this end alone:
did not confirm the update: b'Failed to decode' (this resolver sent
uncompressed data (COMPRESS: False), so the firewall is set the other way;
they must match)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A
COMPRESSmismatch between a resolver and a firewall reported onlyFailed to decode, the same answer as a corrupt payload or malformed JSON, withnothing to say which of the three it was or which end was wrong. Compression is
configuration at both ends and is deliberately not signalled on the wire, so
that is the only way a mismatch can ever surface.
The daemon names the direction
The lz4 frame magic settles it in four bytes. Both directions, each proven
against a running daemon:
COMPRESS: Truepayload is not an lz4 frame but COMPRESS is on: the sender is not compressing. COMPRESS must match at both endsCOMPRESS: Falsepayload is an lz4 frame but COMPRESS is off: the sender is compressing. COMPRESS must match at both endsThe reply stays
Failed to decode, because PROTOCOL.md's reply set is fixed anda test pins it. A frame whose magic is intact but whose body is damaged is still
reported as corruption, so the new message cannot mislead the other way; that
has its own test.
The resolver names it too
An operator reads the resolver's log first, and the resolver knows what it sent,
which fixes the direction without seeing the firewall at all:
Every refusal now carries what it usually means — framing skew for
Bad length,release skew for
Missing kind, no routable address forNo records. A testasserts each hint corresponds to a reply string PROTOCOL.md documents, so advice
cannot outlive the refusal it explains.
A transport error is no longer called a decode failure
Any read error that was not a timeout was answered
Failed to decode, so abroken connection looked to the sender like a malformed message — and would have
muddied exactly this diagnosis. The protocol has no reply for a transport fault
and the connection has already broken, so it is logged as itself and closed.
Known limit
Over UDP a refused datagram gets no reply, by design, so a mismatch there is
named only in the firewall's log; the resolver sees the circuit breaker open.
Answering an unverified sender would make the daemon a reflector.
Testing
cargo fmt --checkandclippy -D warningscleanrelease daemon, with the messages above captured from its log