Skip to content

feat(cast): Chromecast mDNS discovery - #75

Open
susamn wants to merge 1 commit into
feature/cast-chromecast-protofrom
feature/cast-mdns
Open

feat(cast): Chromecast mDNS discovery#75
susamn wants to merge 1 commit into
feature/cast-chromecast-protofrom
feature/cast-mdns

Conversation

@susamn

@susamn susamn commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Stacked on the castproto PR.

internal/cast/mdns.go browses _googlecast._tcp and assembles each device from its PTR/SRV/TXT/A records, accumulating records mDNS splits across packets. Wires chromecastProvider.Discover.

Deviation from the plan: hand-written DNS-SD query + wire parser (name compression, pointer-loop guard) instead of github.com/hashicorp/mdns — that dep also pulls miekg/dns + golang.org/x/net and bumped x/net/x/text project-wide. The query is one fixed PTR; few record types needed.

Tests use hand-built DNS packets. No new dependencies.

internal/cast/mdns.go browses for _googlecast._tcp devices and assembles
each from its PTR/SRV/TXT/A records, accumulating records that mDNS
splits across packets. Wires chromecastProvider.Discover to it (Play/
Stop/Status still stubbed -- the control channel is the next commit).

Self-contained: a small hand-written DNS-SD query and wire parser (name
compression, pointer-loop guard, oversize guards) rather than a general
mDNS module -- the query is one fixed PTR and the needed record types are
few. Avoids pulling github.com/hashicorp/mdns + github.com/miekg/dns +
golang.org/x/net, which also bumped x/net and x/text project-wide.

Tests use hand-built DNS packets: single-packet assembly, cross-packet
accumulation, compression-pointer following, pointer-loop rejection.
No new dependencies.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JBJdG8Qenand5i16WT6BHG
@susamn
susamn force-pushed the feature/cast-mdns branch from 96472af to 5cd48bf Compare August 28, 2026 02:54
@susamn

susamn commented Aug 28, 2026

Copy link
Copy Markdown
Owner Author

Updated: the initial implementation only listened on an ephemeral unicast port, so it caught almost nothing on a real network (mDNS responders answer via multicast, and a system mDNS daemon like avahi holding :5353 means the kernel may not hand us the multicast traffic).

Now: a dedicated ephemeral unicast socket sends the query with the unicast-response (QU) bit set (first reply comes straight back to us), plus the 224.0.0.251:5353 group joined per interface (a host with docker0 alongside wlan otherwise joins the wrong one), plus the query re-sent twice more (mDNS is lossy). SRV/TXT records are now filtered to _googlecast._tcp so other services on the LAN don't create phantom targets.

Verified against a live network: 7/7 real Cast devices found with id/name/model, consistently across runs. Still no new dependencies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant