fix(gateway): advertise bonjour hostname
parent
36f21c5a4f
commit
2b71ea21ad
|
|
@ -49,6 +49,15 @@ If browsing shows instances but resolving fails, you’re usually hitting a LAN
|
||||||
- **Bonjour doesn’t cross networks**: London/Vienna style setups require Tailnet (MagicDNS/IP) or SSH.
|
- **Bonjour doesn’t cross networks**: London/Vienna style setups require Tailnet (MagicDNS/IP) or SSH.
|
||||||
- **Multicast blocked**: some Wi‑Fi networks (enterprise/hotels) disable mDNS; expect “no results”.
|
- **Multicast blocked**: some Wi‑Fi networks (enterprise/hotels) disable mDNS; expect “no results”.
|
||||||
- **Sleep / interface churn**: macOS may temporarily drop mDNS results when switching networks; retry.
|
- **Sleep / interface churn**: macOS may temporarily drop mDNS results when switching networks; retry.
|
||||||
|
- **Browse works but resolve fails (iOS “NoSuchRecord”)**: make sure the advertiser publishes a valid SRV target hostname.
|
||||||
|
- Implementation detail: `@homebridge/ciao` defaults `hostname` to the *service instance name* when `hostname` is omitted. If your instance name contains spaces/parentheses, some resolvers can fail to resolve the implied A/AAAA record.
|
||||||
|
- Fix: set an explicit DNS-safe `hostname` (single label; no `.local`) in `src/infra/bonjour.ts`.
|
||||||
|
|
||||||
|
## Escaped instance names (`\\032`)
|
||||||
|
Bonjour/DNS-SD often escapes bytes in service instance names as decimal `\\DDD` sequences (e.g. spaces become `\\032`).
|
||||||
|
|
||||||
|
- This is normal at the protocol level.
|
||||||
|
- UIs should decode for display (iOS uses `BonjourEscapes.decode` in `apps/shared/ClawdisKit`).
|
||||||
|
|
||||||
## Disabling / configuration
|
## Disabling / configuration
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ const { startGatewayBonjourAdvertiser } = await import("./bonjour.js");
|
||||||
describe("gateway bonjour advertiser", () => {
|
describe("gateway bonjour advertiser", () => {
|
||||||
type ServiceCall = {
|
type ServiceCall = {
|
||||||
name?: unknown;
|
name?: unknown;
|
||||||
|
hostname?: unknown;
|
||||||
|
domain?: unknown;
|
||||||
txt?: unknown;
|
txt?: unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -66,6 +68,8 @@ describe("gateway bonjour advertiser", () => {
|
||||||
>;
|
>;
|
||||||
expect(masterCall?.[0]?.type).toBe("clawdis-master");
|
expect(masterCall?.[0]?.type).toBe("clawdis-master");
|
||||||
expect(masterCall?.[0]?.port).toBe(2222);
|
expect(masterCall?.[0]?.port).toBe(2222);
|
||||||
|
expect(masterCall?.[0]?.domain).toBe("local");
|
||||||
|
expect(masterCall?.[0]?.hostname).toBe("test-host");
|
||||||
expect((masterCall?.[0]?.txt as Record<string, string>)?.lanHost).toBe(
|
expect((masterCall?.[0]?.txt as Record<string, string>)?.lanHost).toBe(
|
||||||
"test-host.local",
|
"test-host.local",
|
||||||
);
|
);
|
||||||
|
|
@ -75,6 +79,8 @@ describe("gateway bonjour advertiser", () => {
|
||||||
|
|
||||||
expect(bridgeCall?.[0]?.type).toBe("clawdis-bridge");
|
expect(bridgeCall?.[0]?.type).toBe("clawdis-bridge");
|
||||||
expect(bridgeCall?.[0]?.port).toBe(18790);
|
expect(bridgeCall?.[0]?.port).toBe(18790);
|
||||||
|
expect(bridgeCall?.[0]?.domain).toBe("local");
|
||||||
|
expect(bridgeCall?.[0]?.hostname).toBe("test-host");
|
||||||
expect((bridgeCall?.[0]?.txt as Record<string, string>)?.bridgePort).toBe(
|
expect((bridgeCall?.[0]?.txt as Record<string, string>)?.bridgePort).toBe(
|
||||||
"18790",
|
"18790",
|
||||||
);
|
);
|
||||||
|
|
@ -109,6 +115,8 @@ describe("gateway bonjour advertiser", () => {
|
||||||
|
|
||||||
const [masterCall] = createService.mock.calls as Array<[ServiceCall]>;
|
const [masterCall] = createService.mock.calls as Array<[ServiceCall]>;
|
||||||
expect(masterCall?.[0]?.name).toBe("Mac (Clawdis)");
|
expect(masterCall?.[0]?.name).toBe("Mac (Clawdis)");
|
||||||
|
expect(masterCall?.[0]?.domain).toBe("local");
|
||||||
|
expect(masterCall?.[0]?.hostname).toBe("Mac");
|
||||||
expect((masterCall?.[0]?.txt as Record<string, string>)?.lanHost).toBe(
|
expect((masterCall?.[0]?.txt as Record<string, string>)?.lanHost).toBe(
|
||||||
"Mac.local",
|
"Mac.local",
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,8 @@ export async function startGatewayBonjourAdvertiser(
|
||||||
type: "clawdis-master",
|
type: "clawdis-master",
|
||||||
protocol: Protocol.TCP,
|
protocol: Protocol.TCP,
|
||||||
port: opts.sshPort ?? 22,
|
port: opts.sshPort ?? 22,
|
||||||
|
domain: "local",
|
||||||
|
hostname,
|
||||||
txt: {
|
txt: {
|
||||||
...txtBase,
|
...txtBase,
|
||||||
sshPort: String(opts.sshPort ?? 22),
|
sshPort: String(opts.sshPort ?? 22),
|
||||||
|
|
@ -88,6 +90,8 @@ export async function startGatewayBonjourAdvertiser(
|
||||||
type: "clawdis-bridge",
|
type: "clawdis-bridge",
|
||||||
protocol: Protocol.TCP,
|
protocol: Protocol.TCP,
|
||||||
port: opts.bridgePort,
|
port: opts.bridgePort,
|
||||||
|
domain: "local",
|
||||||
|
hostname,
|
||||||
txt: {
|
txt: {
|
||||||
...txtBase,
|
...txtBase,
|
||||||
transport: "bridge",
|
transport: "bridge",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue