Replace one-shot, blind-sleep mDNS lookups with a warm cache backed by
persistent background queriers:
- PTR (browse): a single ServiceBrowser tracks every service type seen
so far (recreated with the enlarged type set when a new one shows
up, rather than one browser per type), so zeroconf continuously
refreshes it in the background; answers are read straight from the
mDNS cache instead of blocking timeout seconds on every query.
- TXT/SRV: still resolved via get_service_info() (already cache-first
internally), but a background job now periodically re-primes the
cache so it doesn't go cold between queries.
- A/AAAA (bare hostnames): answers are read from the mDNS cache first;
only a first-ever query for a name blocks waiting for a response,
with a background job keeping it warm afterwards.
Periodic refresh jobs are scheduled by a single heap-based scheduler
thread and executed by a fixed pool of 4 worker threads, so the
background thread count stays constant no matter how many distinct
names/services get queried over the proxy's lifetime.
All returned TTLs now reflect the real remaining TTL of the underlying
mDNS record instead of a fixed constant, and goodbye packets (TTL=0)
are handled for free since eviction is delegated to zeroconf's own
cache.
Also add .gitignore for the project-local .venv/ and __pycache__/.
Synthesize an SOA record for the zone, return it for direct SOA
queries, and include it in the authority section of empty responses
so resolvers can negative-cache properly. RCODE stays NOERROR rather
than NXDOMAIN, since mDNS can't reliably prove non-existence.
Enable dual-stack mDNS lookups (Zeroconf ip_version was set to a value
that matched no IPVersion member), add AAAA query handling, and include
AAAA glue records for SRV targets. Link-local IPv6/IPv4 addresses are
filtered out since they aren't usable by clients off the local link.