-
Notifications
You must be signed in to change notification settings - Fork 0
Discovery and Pairing
Two machines have to find each other, agree that they trust each other, and keep agreeing after their addresses change. This page covers all three.
47810, TCP and UDP on the same number. For links between two AudioHub machines, that is one port to remember and one port to open if a firewall is in the way.
| Port | Who listens | What it carries |
|---|---|---|
| 47810/TCP | the audio service, on all interfaces | the control channel, encrypted after an identity handshake pinned to the peer's fingerprint |
| 47810/UDP | the audio service, on all interfaces | media, when the connection method is Direct (UDP) |
| 5353/UDP | mDNS — while advertising, while scanning, and while the AirPlay receiver is on | the local-network broadcast described below |
| random | the audio service, on 127.0.0.1 only | IPC between the service and its UI |
| 47800/TCP | the app, only when you switch it on, on 127.0.0.1 only | the browser interface |
| chosen once/TCP | the AirPlay receiver, only while it is on | AirPlay control; the number is picked at first start, then remembered, shown in its status row and advertised over mDNS |
| ephemeral/TCP+UDP | the AirPlay receiver, per sender session | the encrypted event channel, buffered audio, audio data, audio control and timing — negotiated at connect time, not fixed numbers |
| 319/UDP, 320/UDP | Windows only — the AirPlay receiver, while it is on | PTP, the clock AirPlay 2 times playback against |
The last three rows apply only to AirPlay receiving, which is off by default. With it off, the table above them is the complete list.
The PTP row is Windows-only because on macOS the kernel itself owns UDP 319/320 and will not hand those packets to an ordinary application socket. AudioHub therefore does not bind them there; it asks the system's own clock service for the timing instead, so there is no extra macOS port to open.
A firewall between you and an AirPlay sender has to allow ephemeral ports, not one number. Only the control port is advertised; every other socket a session uses is chosen when the sender connects.
The audio service fails to start. It does not fall back to another port. The
status dot stays offline and the service log records
start failed: bind tcp :47810. The remedies are to free the port, or to start
the service by hand with --port N — and then to give peers that number when
they type an address.
The control port is read-only in the interface: Settings › Network shows it
with a Read-only badge and nothing there changes it. --port N on the service
is the only thing that does.
The IPC port is picked at startup and written to ipc.json in the
config directory; it never leaves the loopback
interface, which is the fact that keeps
"local only" locked.
Two independent paths, and the second one always works.
Automatic (mDNS). Switch on Settings › Network › Advertise on LAN and other AudioHub installations on the same subnet see this machine when they scan. Nothing is published to the internet.
Manual (IP[:port]). Open Add peer on the main panel and type the peer's
address. This works across subnets, through routed networks and through L3
VPNs, and it does not depend on advertising being on at either end. If mDNS is
blocked — plenty of managed networks block it — this is the path, not a fallback.
A ws:// address may also be entered, which selects the tunnelled transport;
see the tunnel address. Pairing itself
cannot be done over a tunnel: pair over IP:port first, then set the tunnel
address on that peer's detail page.
Four fields:
| Field | Why it is there |
|---|---|
Machine name (name) |
so the scan list is readable |
Control port (port) |
so the scanner knows where to connect |
Identity fingerprint (fp) |
so the scan list can tell this machine, already paired and stranger apart |
Record version (v) |
so a later format change can be told apart from this one |
The fingerprint deserves a note, because publishing a cryptographic identity on a broadcast sounds worse than it is: it is a digest of the public key, and any host that can reach the control port obtains it during the handshake anyway. Broadcasting it does not disclose anything a port scan would not. What it buys is a scan list that can mark entries correctly instead of showing three identical-looking strangers.
Turning Advertise on LAN off means this machine is no longer discoverable. It does not affect anything else: pairing by typed IP still works, inbound connections are still accepted, and scanning for other machines still works. It also does not free 5353 — scanning binds that port too, and so does the AirPlay receiver.
The service reports the wish and the reality as two separate facts, and the interface shows the gap rather than pretending. With the switch on but advertising not in force, Settings › Network prints:
⚠ Enabled, but advertising is not active, so other devices cannot discover this one. On macOS, allow AudioHub under System Settings › Privacy & Security › Local Network, then turn this setting off and back on.
No restart is needed — toggling the switch retries the registration. See Platform Notes for what the Local Network grant does and does not cover.
Every installation generates a long-lived key pair on first run. The fingerprint is a short digest of the public half — 16 lowercase hex characters — and it is the only thing that identifies a machine: not its name, not its IP, both of which change.
| Whose | Where |
|---|---|
| Your own | Settings › General › Fingerprint — click the value to copy it. Also in the panel that opens when you click the status dot in the window's top corner (the dot itself carries no text) |
| A peer's | Its detail page, under Identity, with a Copy button. Rows in the scan list show a shortened form |
Two places rely on it:
- Pairing. The PIN exchange is SPAKE2, a password-authenticated key agreement, and it is what writes the peer's public key into the trust record. The PIN is short-lived and single-use; the fingerprint is what is remembered. The pairing flow has no "compare these two strings" screen — there is nothing for you to check by hand during the exchange.
- Every later connection. The peer signs a challenge, and the signature is verified against the key pinned in the trust record — never against the key it presents on the wire, and never against a certificate authority. A host that answers on the right address and port but holds a different key is refused, which is what makes reconnecting to a changed IP safe. This is not TLS: the control channel is an X25519 + HKDF-SHA256 + ChaCha20-Poly1305 upgrade performed after that signature check, so nothing here behaves like a TLS endpoint or can be inspected with TLS tooling.
If you want to compare fingerprints by eye, do it after pairing: the value on the peer's detail page here should equal the value in Settings › General on that machine.
One side presses Pairing Mode and shows a six-digit PIN; the other side opens Add peer and enters that PIN together with the address. That is the whole ceremony.
Five properties worth knowing:
- Trust is bidirectional. One side initiates, both end up trusting. After it succeeds each machine appears in the other's list — there is no second, reversed pairing to perform.
- The PIN expires after two minutes. The countdown ring on the pairing panel is the authority; when it runs out, press Enable again for a fresh PIN.
- The PIN is single-use. One successful pairing closes the window. Setting up three machines means arming it three times.
- Five wrong PINs close the window too. After that even the correct PIN is refused until you press Enable again.
- One attempt at a time. A second machine trying to pair while another attempt is in flight is told pairing is not enabled.
If it fails, the interface lists the three things to check — pairing mode enabled on the far side, PIN not expired, address reachable — but it cannot tell you which one it was. That is not a UI shortcut: the far side answers "pairing not enabled" for an expired PIN and for a concurrent attempt as well, so the information does not exist on the wire. A wrong PIN is the one failure that reports itself distinctly.
The moment pairing succeeds the peer's virtual devices are created — subject to three conditions that surprise people:
- Pairing does not open a control connection, so the peer is not yet online.
With
Mark names offlineon (the default) the devices appear with an offline marker in their name and pass no audio until the two machines connect. - Devices are published per direction. A peer with no default input publishes only a speaker, not a pair; a peer with neither endpoint publishes nothing.
- If you have turned on
Remove on disconnect, nothing appears at all until the peer is online.
See Mode B.
The same exchange, if the UI is not where you are:
audiohub ctl pair --addr <ip>[:<port>] --pin <pin>
The port may be omitted, in which case 47810 is assumed. This talks to the local service over the same IPC contract the UI uses, so the result is identical and appears in the UI immediately.
There is also a standalone
audiohub pair --to <ip>:<port> --pin <pin>. It is a probe tool, not an equivalent: it runs the handshake in its own process and writes the trust file behind the running service's back, and because it has no listener of its own it advertises a guessed port to the peer unless you pass--listen-port <the service's real port>. Usectl pairunless you know why you want the other one.
Unpairing is not "disconnect". It is the removal of the trust record, and it is deliberately abrupt:
- Both directions of trust are revoked.
- All sessions with that peer close immediately.
- The virtual devices for that peer are removed from this system
unconditionally, regardless of the
Remove on disconnectsetting. - The four transport settings remembered for that peer are discarded, so re-pairing later does not silently inherit them.
The peer is told only if it is connected at that moment. If it is asleep or offline, no notification is sent; it learns the next time it tries to connect to you and is refused with a signed proof, and removes its devices then. A machine that never comes back keeps a set of permanently-offline devices in its sound settings until someone removes them by hand. That asymmetry is the reason unpairing asks for confirmation and lists, by name, the devices that are about to disappear.
If one of the removed devices was the system's default output or input, the OS picks another one, exactly as it does when you unplug an interface.
To use that machine again, pair again. There is no "re-trust" shortcut, on purpose: the fingerprint check is the whole point of the exercise.
Addresses change; the fingerprint does not.
The service remembers one address per peer, refreshed every time that peer connects, and dials that — verifying the fingerprint before anything else happens. It does not work down a list, because there is no list: the Addresses card on the peer's detail page is a log for you to read, not a set of candidates the service falls back through.
Only the side that originally dialled out retries. Its backoff ladder is 1 → 2 → 5 → 10 → 30 seconds, and the last rung repeats. This is why a paired laptop that moves between two networks generally reappears without being told anything — usually because it dials you, which refreshes the address on this side.
Open Add peer › Reconnect peer and give the fingerprint (a unique prefix is enough) with an optional address. That is a different operation from pairing: no PIN, because the two machines already trust each other.
Two states where the service will not dial, by design:
-
No recorded port. If the peer paired without advertising a port that could
be believed, there is nothing to dial. The peer is still perfectly usable — it
has to be the one to connect, or you have to supply
host:portyourself. -
Inbound-only. A peer whose dial policy says this machine must never
originate the connection is never dialled and never retried; it is expected to
connect to you. The interface has no separate word for that state, so such a
peer simply looks offline until it does. That is a working configuration, not a
fault. The dial policy has no control in the interface; it is set from the CLI
with
audiohub ctl peer-transport --peer <fingerprint> --tier <tier> --dial-policy inbound_only(the two flags must be given together).
Start here
Using AudioHub
- Window and tray
- Operating Modes
- Virtual Driver
- Discovery and Pairing
- Peer detail page
- Share Protocols (Sharing tab)
- Web Access
How it behaves
Reference
- Settings Reference
- Platform Notes
- Firewall and network
- CLI Reference
- Versions and Compatibility
- Glossary
- Licenses and Attribution
Troubleshooting and removal
This wiki describes AudioHub 1.0.0.