Skip to content

feat: discover Lan Mouse devices on the local network (mDNS + broadcast) - #532

Open
ekremyk2 wants to merge 2 commits into
feschber:mainfrom
ekremyk2:discovery
Open

ekremyk2 wants to merge 2 commits into
feschber:mainfrom
ekremyk2:discovery

Conversation

@ekremyk2

Copy link
Copy Markdown

What this does

Lan Mouse devices on the same network find each other, so they can be added without typing a hostname or IP address.

  • Each instance advertises itself as a _lan-mouse._udp DNS-SD service over mDNS (the pure-Rust mdns-sd crate, so no Avahi/Bonjour dependency). The TXT record carries the device name, its certificate fingerprint and its OS.
  • Each instance also broadcasts a small JSON beacon on UDP port 4241 every 5 seconds and answers new devices directly. Many home routers drop multicast between Wi-Fi and Ethernet. That's how I ran into this: a Windows PC on Ethernet and a MacBook on Wi-Fi never saw each other's mDNS announcements. Reports from both methods are merged per device, and beacons expire when a device goes away.
  • CLI:
    • lan-mouse cli discover lists nearby devices with their addresses and fingerprints.
    • lan-mouse cli add-discovered <name> <left|right|top|bottom> adds (or reuses) a client for a device and activates it.
    • lan-mouse cli authorize-discovered <name> lets that device control this one.
  • A client that matches a discovered device, by hostname or by one of its configured or resolved addresses, gets the device's announced addresses. The client keeps working when DHCP hands out a new IP.
  • discovery = false in the config turns it off. It needs UDP 5353 (mDNS) and 4241 (broadcast); the firewalld service file is updated.

It also includes a small fix the new commands rely on: every CLI command now waits until the service has handled it (a Ping/Pong round trip). On Windows, the CLI exiting right after writing a request could reset the IPC connection, and the service dropped requests it had not read yet. I'm happy to split this into its own PR if you prefer.

Related

Security note

authorize-discovered trusts the fingerprint a device announces on the network, so it is only meant for trusted networks. discover lists the fingerprints for comparison, and the README says so.

Not included

There is no GUI for discovered devices yet; it's CLI only, like the README says. If you like the approach, I can add a "nearby devices" list to the GTK window in a follow-up.

Testing

  • Windows 11 on Ethernet and macOS on Wi-Fi, behind a router that filters multicast between the two: they found each other through the broadcast beacons, then were added and connected in both directions.
  • Unit tests cover hostname matching, address filtering, the beacon round trip and merging mDNS with beacon reports. Two #[ignore]d tests discover a peer over real sockets.
  • Linux was built and tested by CI only. All build, check and test jobs pass on Linux, Windows and macOS (Apple silicon and Intel).
  • The only red job is clippy on Linux, and it comes from code this PR doesn't touch: Rust 1.99's new double_must_use lint flags the #[async_trait] traits in input-emulation, so main fails it too now. chore(deps): update async-trait to 0.1.92 (fixes clippy with Rust 1.99) #531 fixes that by updating async-trait to 0.1.92.

AI disclosure

This was written with the help of AI (Claude by Anthropic) and tested on my own Windows PC and Mac.

ekremyk2 and others added 2 commits October 13, 2026 16:23
Advertise each instance as a `_lan-mouse._udp` DNS-SD service and browse
for other instances. Nearby devices are listed with `cli discover`, added
with `cli add-discovered <name> <pos>` and allowed to control this device
with `cli authorize-discovered <name>`. Clients whose hostname matches a
discovered device get its announced addresses kept up to date. Discovery
can be turned off with `discovery = false` in the config.

Also make every CLI command wait until the service has handled it. On
Windows, exiting right after a request could reset the IPC connection
and the service dropped requests it had not read yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dress

Some routers drop multicast between Wi-Fi and Ethernet, so devices on
different sides never see each other's mDNS announcements. Each instance
now also broadcasts a small JSON beacon on UDP port 4241 every few seconds
(and answers beacons directly), and reports from both methods are merged
per device. Beacons time out when a device stops sending them.

A discovered device now also belongs to a client when it announces one of
the client's configured or resolved addresses, not only its hostname.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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