Files
NetMesh/electron/bridges/macLocalNetworkAccess.test.cjs

915 lines
28 KiB
JavaScript
Raw Normal View History

"use strict";
const test = require("node:test");
const assert = require("node:assert/strict");
const { EventEmitter } = require("node:events");
const {
DEFAULT_PROBE_TIMEOUT_MS,
DEFAULT_PROBE_HOLD_MS,
DISCARD_PORT,
isLocalNetworkHostname,
isLocalMdnsName,
resolveFirstTcpEndpoint,
resolveLanProbeTarget,
annotateMacLocalNetworkErrorMessage,
attachMacLocalNetworkProbeResult,
createMacLocalNetworkAccessGate,
} = require("./macLocalNetworkAccess.cjs");
test("DEFAULT_PROBE_TIMEOUT_MS is a few seconds, not tens of seconds", () => {
assert.ok(DEFAULT_PROBE_TIMEOUT_MS >= 500);
assert.ok(DEFAULT_PROBE_TIMEOUT_MS <= 5_000);
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
});
assert.equal(gate.getProbeTimeoutMs(), DEFAULT_PROBE_TIMEOUT_MS);
});
test("DEFAULT_PROBE_HOLD_MS keeps the UDP socket open briefly for TCC", () => {
assert.ok(DEFAULT_PROBE_HOLD_MS >= 200);
assert.ok(DEFAULT_PROBE_HOLD_MS <= 2_000);
});
test("DISCARD_PORT is the IANA discard service used by Apple TN3179", () => {
assert.equal(DISCARD_PORT, 9);
});
test("isLocalNetworkHostname recognizes RFC1918, link-local, and CGNAT", () => {
assert.equal(isLocalNetworkHostname("192.168.5.22"), true);
assert.equal(isLocalNetworkHostname("10.0.0.1"), true);
assert.equal(isLocalNetworkHostname("172.16.9.1"), true);
assert.equal(isLocalNetworkHostname("172.31.255.1"), true);
assert.equal(isLocalNetworkHostname("169.254.1.1"), true);
assert.equal(isLocalNetworkHostname("100.64.0.1"), true);
assert.equal(isLocalNetworkHostname("[fd12::1]"), true);
assert.equal(isLocalNetworkHostname("fe80::1"), true);
assert.equal(isLocalNetworkHostname("::ffff:192.168.1.9"), true);
});
test("isLocalNetworkHostname rejects public, loopback, empty, and non-IP hostnames", () => {
assert.equal(isLocalNetworkHostname("8.8.8.8"), false);
assert.equal(isLocalNetworkHostname("1.1.1.1"), false);
assert.equal(isLocalNetworkHostname("172.15.0.1"), false);
assert.equal(isLocalNetworkHostname("172.32.0.1"), false);
assert.equal(isLocalNetworkHostname("127.0.0.1"), false);
assert.equal(isLocalNetworkHostname("localhost"), false);
assert.equal(isLocalNetworkHostname("example.com"), false);
assert.equal(isLocalNetworkHostname("nas.local"), false);
// Must not treat public names that merely start with fc/fd as ULA.
assert.equal(isLocalNetworkHostname("fda.gov"), false);
assert.equal(isLocalNetworkHostname("fdcorp.example"), false);
assert.equal(isLocalNetworkHostname("fc-host.example"), false);
assert.equal(isLocalNetworkHostname(""), false);
assert.equal(isLocalNetworkHostname(null), false);
});
test("isLocalMdnsName recognizes .local hostnames that require Local Network access", () => {
assert.equal(isLocalMdnsName("nas.local"), true);
assert.equal(isLocalMdnsName("NAS.LOCAL."), true);
assert.equal(isLocalMdnsName("printer.local"), true);
assert.equal(isLocalMdnsName("example.com"), false);
assert.equal(isLocalMdnsName("192.168.1.1"), false);
assert.equal(isLocalMdnsName("localhost"), false);
assert.equal(isLocalMdnsName(""), false);
});
test("resolveFirstTcpEndpoint prefers proxy, then jump host, then target", () => {
assert.deepEqual(
resolveFirstTcpEndpoint({
hostname: "10.0.0.9",
port: 2222,
proxy: { type: "socks5", host: "192.168.0.2", port: 1080 },
jumpHosts: [{ hostname: "192.168.1.1", port: 2200 }],
}),
{ hostname: "192.168.0.2", port: 1080 },
);
assert.deepEqual(
resolveFirstTcpEndpoint({
hostname: "10.0.0.9",
port: 2222,
jumpHosts: [{ hostname: "192.168.1.1", port: 2200 }],
}),
{ hostname: "192.168.1.1", port: 2200 },
);
assert.deepEqual(
resolveFirstTcpEndpoint({ hostname: "192.168.5.22", port: 22 }),
{ hostname: "192.168.5.22", port: 22 },
);
assert.deepEqual(
resolveFirstTcpEndpoint({ host: "10.1.2.3" }),
{ hostname: "10.1.2.3", port: 22 },
);
});
test("resolveFirstTcpEndpoint prefers the first jump proxy over session proxy and jump host", () => {
assert.deepEqual(
resolveFirstTcpEndpoint({
hostname: "10.0.0.9",
port: 22,
proxy: { type: "socks5", host: "203.0.113.10", port: 1080 },
jumpHosts: [{
hostname: "nas.local",
port: 22,
proxy: { type: "http", host: "192.168.0.50", port: 8080 },
}],
}),
{ hostname: "192.168.0.50", port: 8080 },
);
// Active ProxyCommand is terminal: do not fall through to LAN hostnames.
assert.deepEqual(
resolveFirstTcpEndpoint({
hostname: "nas.local",
proxy: { type: "command", command: "nc -X connect" },
}),
{ hostname: "", port: 0, skipProbe: true, reason: "command-proxy" },
);
assert.deepEqual(
resolveFirstTcpEndpoint({
hostname: "10.0.0.9",
proxy: { type: "socks5", host: "192.168.0.2", port: 1080 },
jumpHosts: [{
hostname: "nas.local",
proxy: { type: "command", command: "nc -X connect" },
}],
}),
{ hostname: "", port: 0, skipProbe: true, reason: "command-proxy" },
);
});
test("createMacLocalNetworkAccessGate skips probing when ProxyCommand owns the first hop", async () => {
let creates = 0;
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
dgram: {
createSocket() {
creates += 1;
throw new Error("must not probe past ProxyCommand");
},
},
});
const result = await gate.ensureAccess({
hostname: "nas.local",
port: 22,
proxy: { type: "command", command: "cloudflared access ssh" },
});
assert.deepEqual(result, { skipped: true, reason: "command-proxy" });
assert.equal(creates, 0);
});
test("createMacLocalNetworkAccessGate shares one deadline across DNS and UDP probe", async () => {
const safetyTimeouts = [];
let now = 5_000;
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probeTimeoutMs: 500,
probeHoldMs: 5,
setTimer: (fn, ms) => {
safetyTimeouts.push(ms);
// DNS success clears its timer; only fire later UDP hang timers.
if (safetyTimeouts.length > 1) queueMicrotask(fn);
return { ms };
},
clearTimer() {},
lookup: async () => {
now += 200;
return [{ address: "192.168.7.37", family: 4 }];
},
dgram: {
createSocket() {
class HangSocket extends EventEmitter {
connect() {}
close() {}
}
return new HangSocket();
},
},
});
const originalNow = Date.now;
Date.now = () => now;
try {
await gate.ensureAccess({ hostname: "dev-viet", port: 22 });
} finally {
Date.now = originalNow;
}
// DNS armed with the full budget; UDP families inherit only the remainder.
assert.ok(safetyTimeouts.includes(500), `expected DNS budget arm, got ${JSON.stringify(safetyTimeouts)}`);
const udpBudgets = safetyTimeouts.filter((ms) => ms !== 500);
assert.ok(udpBudgets.length >= 1, `expected UDP budget arm(s), got ${JSON.stringify(safetyTimeouts)}`);
assert.ok(udpBudgets.every((ms) => ms <= 300), `UDP budgets should be residual, got ${JSON.stringify(udpBudgets)}`);
});
test("resolveLanProbeTarget keeps LAN literals and .local names", async () => {
assert.deepEqual(
await resolveLanProbeTarget("192.168.7.37"),
{ hostname: "192.168.7.37", reason: "literal" },
);
assert.deepEqual(
await resolveLanProbeTarget("dev-viet.local"),
{ hostname: "dev-viet.local", reason: "mdns" },
);
});
test("resolveLanProbeTarget DNS-resolves hostnames and picks a LAN address", async () => {
const target = await resolveLanProbeTarget("dev-viet", {
lookup: async () => [
{ address: "8.8.8.8", family: 4 },
{ address: "192.168.7.37", family: 4 },
],
});
assert.deepEqual(target, { hostname: "192.168.7.37", reason: "resolved" });
});
test("resolveLanProbeTarget returns null for public-only hostnames", async () => {
const target = await resolveLanProbeTarget("example.com", {
lookup: async () => [{ address: "93.184.216.34", family: 4 }],
});
assert.equal(target, null);
});
test("annotateMacLocalNetworkErrorMessage only rewrites LAN unreachability on darwin", () => {
const base = "connect EHOSTUNREACH 192.168.5.22:22";
const annotated = annotateMacLocalNetworkErrorMessage(base, {
platform: "darwin",
hostname: "192.168.5.22",
});
assert.match(annotated, /Local Network/i);
assert.match(annotated, /System Settings/i);
assert.equal(
annotateMacLocalNetworkErrorMessage(base, {
platform: "linux",
hostname: "192.168.5.22",
}),
base,
);
// Message embeds a LAN IP - annotate even when the vault hostname option is public.
assert.match(
annotateMacLocalNetworkErrorMessage(base, {
platform: "darwin",
hostname: "8.8.8.8",
}),
/Local Network/i,
);
assert.equal(
annotateMacLocalNetworkErrorMessage(
"connect EHOSTUNREACH 8.8.8.8:22",
{ platform: "darwin", hostname: "8.8.8.8" },
),
"connect EHOSTUNREACH 8.8.8.8:22",
);
assert.equal(
annotateMacLocalNetworkErrorMessage("All configured authentication methods failed", {
platform: "darwin",
hostname: "192.168.5.22",
}),
"All configured authentication methods failed",
);
// Annotate when first hop is LAN even if final target is public.
const viaJump = annotateMacLocalNetworkErrorMessage(base, {
platform: "darwin",
hostname: "8.8.8.8",
firstHopHostname: "192.168.1.1",
});
assert.match(viaJump, /Local Network/i);
});
test("annotateMacLocalNetworkErrorMessage detects LAN IPs embedded in the error text", () => {
const message = "Error: connect EHOSTUNREACH 192.168.7.37:22 - Local (192.168.6.131:58210)";
const annotated = annotateMacLocalNetworkErrorMessage(message, {
platform: "darwin",
// Vault host stored as a DNS name, not a literal IP.
hostname: "dev-viet",
});
assert.match(annotated, /Local Network/i);
});
test("annotateMacLocalNetworkErrorMessage ignores LAN bind addresses on public failures", () => {
const message = "connect EHOSTUNREACH 93.184.216.34:22 - Local (192.168.1.5:58210)";
assert.equal(
annotateMacLocalNetworkErrorMessage(message, {
platform: "darwin",
hostname: "example.com",
}),
message,
);
});
test("annotateMacLocalNetworkErrorMessage detects embedded IPv6 LAN destinations", () => {
const bracketed = "connect EHOSTUNREACH [fd12::1]:22";
assert.match(
annotateMacLocalNetworkErrorMessage(bracketed, {
platform: "darwin",
hostname: "ula-host",
}),
/Local Network/i,
);
const bare = "connect EHOSTUNREACH fe80::1:22 - Local ([fe80::abcd]:5555)";
assert.match(
annotateMacLocalNetworkErrorMessage(bare, {
platform: "darwin",
hostname: "link-local-host",
}),
/Local Network/i,
);
});
test("annotateMacLocalNetworkErrorMessage ignores .local targets behind a public first hop", () => {
const message = "connect EHOSTUNREACH 93.184.216.34:1080";
assert.equal(
annotateMacLocalNetworkErrorMessage(message, {
platform: "darwin",
hostname: "nas.local",
firstHopHostname: "93.184.216.34",
}),
message,
);
assert.match(
annotateMacLocalNetworkErrorMessage(message, {
platform: "darwin",
hostname: "nas.local",
firstHopHostname: "nas.local",
}),
/Local Network/i,
);
});
test("annotateMacLocalNetworkErrorMessage ignores downstream LAN addresses behind a public first hop", () => {
const message = "connect EHOSTUNREACH 192.168.1.10:22";
assert.equal(
annotateMacLocalNetworkErrorMessage(message, {
platform: "darwin",
hostname: "nas.local",
firstHopHostname: "proxy.example.com",
}),
message,
);
assert.equal(
annotateMacLocalNetworkErrorMessage(message, {
platform: "darwin",
hostname: "192.168.1.10",
firstHopHostname: "93.184.216.34",
}),
message,
);
});
test("annotateMacLocalNetworkErrorMessage keeps LAN guidance for hostname-based LAN first hops", () => {
const message = "connect EHOSTUNREACH 192.168.1.20:22";
assert.match(
annotateMacLocalNetworkErrorMessage(message, {
platform: "darwin",
hostname: "app.internal",
firstHopHostname: "bastion.lan",
}),
/Local Network/i,
);
});
test("annotateMacLocalNetworkErrorMessage keeps LAN guidance for unqualified first hops", () => {
const message = "connect EHOSTUNREACH 192.168.7.37:22";
assert.match(
annotateMacLocalNetworkErrorMessage(message, {
platform: "darwin",
hostname: "app.example.com",
firstHopHostname: "dev-viet",
}),
/Local Network/i,
);
});
test("annotateMacLocalNetworkErrorMessage uses carried resolved first-hop addresses", () => {
const message = "connect EHOSTUNREACH 192.168.1.20:22";
assert.match(
annotateMacLocalNetworkErrorMessage(message, {
platform: "darwin",
hostname: "app.example.com",
firstHopHostname: "bastion.example.com",
firstHopResolvedAddress: "192.168.1.20",
}),
/Local Network/i,
);
assert.equal(
annotateMacLocalNetworkErrorMessage(message, {
platform: "darwin",
hostname: "app.example.com",
firstHopHostname: "bastion.example.com",
}),
message,
);
});
test("attachMacLocalNetworkProbeResult forwards resolved first-hop for direct starts", () => {
const options = {
hostname: "app.example.com",
jumpHosts: [{ hostname: "bastion.example.com", port: 22 }],
};
const attached = attachMacLocalNetworkProbeResult(options, {
probed: true,
hostname: "192.168.1.20",
});
assert.equal(attached._macLocalNetworkResolvedFirstHop, "192.168.1.20");
assert.match(
annotateMacLocalNetworkErrorMessage("connect EHOSTUNREACH 192.168.1.20:22", {
platform: "darwin",
hostname: attached.hostname,
firstHopHostname: "bastion.example.com",
firstHopResolvedAddress: attached._macLocalNetworkResolvedFirstHop,
}),
/Local Network/i,
);
assert.equal(
attachMacLocalNetworkProbeResult(options, { skipped: true, reason: "not-local-network" })
._macLocalNetworkResolvedFirstHop,
undefined,
);
});
test("annotateMacLocalNetworkErrorMessage ignores ProxyCommand errors even with LAN evidence", () => {
const localName = "Network is unreachable";
assert.equal(
annotateMacLocalNetworkErrorMessage(localName, {
platform: "darwin",
hostname: "nas.local",
firstHopHostname: "",
skipProbe: true,
}),
localName,
);
const childLan = "connect EHOSTUNREACH 192.168.1.10:22";
assert.equal(
annotateMacLocalNetworkErrorMessage(childLan, {
platform: "darwin",
hostname: "nas.local",
firstHopHostname: "",
skipProbe: true,
}),
childLan,
);
});
function createFakeUdpSocket({ onConnect, onError } = {}) {
class FakeUdpSocket extends EventEmitter {
constructor() {
super();
this.closed = false;
this.connectCalls = [];
}
connect(port, host, callback) {
this.connectCalls.push({ port, host });
queueMicrotask(() => {
if (onError) {
this.emit("error", onError);
return;
}
if (typeof callback === "function") callback();
if (typeof onConnect === "function") onConnect(this);
});
}
close() {
this.closed = true;
}
}
return new FakeUdpSocket();
}
test("createMacLocalNetworkAccessGate probes with UDP discard once per LAN endpoint", async () => {
const sockets = [];
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probeHoldMs: 5,
dgram: {
createSocket(type) {
const socket = createFakeUdpSocket();
socket.type = type;
sockets.push(socket);
return socket;
},
},
});
await gate.ensureAccess({ hostname: "192.168.5.22", port: 22 });
await gate.ensureAccess({ hostname: "192.168.5.22", port: 22 });
assert.equal(sockets.length, 1);
assert.equal(sockets[0].type, "udp4");
assert.deepEqual(sockets[0].connectCalls[0], { port: DISCARD_PORT, host: "192.168.5.22" });
assert.equal(sockets[0].closed, true);
});
test("createMacLocalNetworkAccessGate resolves hostnames before probing", async () => {
const sockets = [];
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probeHoldMs: 5,
lookup: async () => [{ address: "192.168.7.37", family: 4 }],
dgram: {
createSocket() {
const socket = createFakeUdpSocket();
sockets.push(socket);
return socket;
},
},
});
const result = await gate.ensureAccess({ hostname: "dev-viet", port: 22 });
assert.equal(result.probed, true);
assert.equal(result.hostname, "192.168.7.37");
assert.deepEqual(sockets[0].connectCalls[0], { port: DISCARD_PORT, host: "192.168.7.37" });
});
test("createMacLocalNetworkAccessGate probes .local names without requiring DNS", async () => {
const sockets = [];
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probeHoldMs: 5,
lookup: async () => {
throw new Error("DNS must not be required for .local");
},
dgram: {
createSocket(type) {
const socket = createFakeUdpSocket();
socket.type = type;
sockets.push(socket);
return socket;
},
},
});
const result = await gate.ensureAccess({ hostname: "nas.local", port: 22 });
assert.equal(result.probed, true);
assert.deepEqual(sockets[0].connectCalls[0], { port: DISCARD_PORT, host: "nas.local" });
assert.equal(sockets[0].type, "udp4");
});
test("createMacLocalNetworkAccessGate retries .local probes over udp6 when udp4 fails", async () => {
const sockets = [];
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probeHoldMs: 5,
dgram: {
createSocket(type) {
const socket = createFakeUdpSocket(
type === "udp4"
? { onError: Object.assign(new Error("getaddrinfo ENOTFOUND"), { code: "ENOTFOUND" }) }
: undefined,
);
socket.type = type;
sockets.push(socket);
return socket;
},
},
});
const result = await gate.ensureAccess({ hostname: "ipv6-only.local", port: 22 });
assert.equal(result.probed, true);
assert.deepEqual(sockets.map((socket) => socket.type), ["udp4", "udp6"]);
assert.deepEqual(sockets[1].connectCalls[0], { port: DISCARD_PORT, host: "ipv6-only.local" });
assert.equal(sockets[1].closed, true);
});
test("createMacLocalNetworkAccessGate shares one timeout across udp4 and udp6 fallbacks", async () => {
const safetyTimeouts = [];
let now = 1_000;
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probeTimeoutMs: 500,
probeHoldMs: 5,
setTimer: (fn, ms) => {
safetyTimeouts.push(ms);
// First family burns its reserved slice before failing.
if (safetyTimeouts.length === 1) now += ms;
queueMicrotask(fn);
return { ms };
},
clearTimer() {},
dgram: {
createSocket() {
class HangSocket extends EventEmitter {
connect() {
// Never connects; each family burns part of the shared budget.
}
close() {}
}
return new HangSocket();
},
},
});
const originalNow = Date.now;
Date.now = () => now;
try {
await gate.ensureAccess({ hostname: "hang.local", port: 22 });
} finally {
Date.now = originalNow;
}
assert.equal(safetyTimeouts.length, 2);
// Budget is split so udp6 always gets an attempt.
assert.equal(safetyTimeouts[0], 250);
assert.equal(safetyTimeouts[1], 250);
});
test("createMacLocalNetworkAccessGate skips non-darwin and non-LAN hosts", async () => {
let creates = 0;
const linuxGate = createMacLocalNetworkAccessGate({
platform: "linux",
forceElectron: true,
dgram: {
createSocket() {
creates += 1;
throw new Error("should not create socket");
},
},
});
await linuxGate.ensureAccess({ hostname: "192.168.5.22", port: 22 });
const darwinGate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
lookup: async () => [{ address: "93.184.216.34", family: 4 }],
dgram: {
createSocket() {
creates += 1;
throw new Error("should not create socket");
},
},
});
await darwinGate.ensureAccess({ hostname: "example.com", port: 22 });
await darwinGate.ensureAccess({ hostname: "fda.gov", port: 22 });
const bareNodeGate = createMacLocalNetworkAccessGate({
platform: "darwin",
versions: {},
dgram: {
createSocket() {
creates += 1;
throw new Error("should not create socket outside Electron");
},
},
});
await bareNodeGate.ensureAccess({ hostname: "192.168.5.22", port: 22 });
assert.equal(creates, 0);
});
test("createMacLocalNetworkAccessGate treats UDP errors as a completed probe", async () => {
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probeHoldMs: 5,
dgram: {
createSocket() {
return createFakeUdpSocket({
onError: Object.assign(new Error("connect EHOSTUNREACH"), { code: "EHOSTUNREACH" }),
});
},
},
});
await gate.ensureAccess({
hostname: "10.0.0.8",
port: 22,
jumpHosts: [{ hostname: "192.168.1.50", port: 2200 }],
});
// Second call must be cached even though the first connect failed.
let secondCreates = 0;
const cachedGate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probedKeys: new Set(["192.168.1.50"]),
dgram: {
createSocket() {
secondCreates += 1;
throw new Error("should use cache");
},
},
});
await cachedGate.ensureAccess({
jumpHosts: [{ hostname: "192.168.1.50", port: 2200 }],
});
assert.equal(secondCreates, 0);
});
test("createMacLocalNetworkAccessGate holds the UDP socket before closing", async () => {
const holds = [];
let resolveConnect;
const connectSeen = new Promise((resolve) => {
resolveConnect = resolve;
});
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probeHoldMs: 25,
setTimer: (fn, ms) => {
holds.push(ms);
return setTimeout(fn, ms);
},
clearTimer: clearTimeout,
dgram: {
createSocket() {
return createFakeUdpSocket({
onConnect(socket) {
resolveConnect(socket);
},
});
},
},
});
const pending = gate.ensureAccess({ hostname: "10.0.0.1", port: 22 });
const socket = await connectSeen;
assert.equal(socket.closed, false);
await pending;
assert.ok(holds.includes(25), `expected hold timer 25ms, got ${JSON.stringify(holds)}`);
assert.equal(socket.closed, true);
});
test("createMacLocalNetworkAccessGate applies the configured probe timeout as a safety net", async () => {
const timeouts = [];
const holdMs = 5;
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probeTimeoutMs: DEFAULT_PROBE_TIMEOUT_MS,
probeHoldMs: holdMs,
setTimer: (fn, ms) => {
timeouts.push(ms);
// Shared-deadline math often arms a residual (e.g. 2999) rather than the
// exact constant. Fire any safety-budget timer; the hang socket never connects.
if (ms > holdMs) queueMicrotask(fn);
return { ms };
},
clearTimer() {},
dgram: {
createSocket() {
class HangSocket extends EventEmitter {
connect() {
// Never connects; safety timeout must finish the probe.
}
close() {}
}
return new HangSocket();
},
},
});
await gate.ensureAccess({ hostname: "10.0.0.1", port: 22 });
const safetyTimeouts = timeouts.filter((ms) => ms > holdMs);
assert.equal(safetyTimeouts.length, 1);
assert.ok(
safetyTimeouts[0] >= DEFAULT_PROBE_TIMEOUT_MS - 50
&& safetyTimeouts[0] <= DEFAULT_PROBE_TIMEOUT_MS,
`expected residual safety budget near ${DEFAULT_PROBE_TIMEOUT_MS}, got ${safetyTimeouts[0]}`
);
});
test("createMacLocalNetworkAccessGate clears the safety timer so the full hold runs after a slow connect", async () => {
const cleared = [];
const holds = [];
const safetyHandles = [];
const safetyMs = 500;
const holdMs = 40;
let resolveConnectReady;
const connectReady = new Promise((resolve) => {
resolveConnectReady = resolve;
});
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probeTimeoutMs: safetyMs,
probeHoldMs: holdMs,
setTimer: (fn, ms) => {
const handle = { ms, fn, cleared: false };
if (ms === holdMs) {
holds.push(ms);
queueMicrotask(fn);
} else if (ms > holdMs) {
// Connect budget may be a residual (e.g. 499) after shared-deadline math.
safetyHandles.push(handle);
}
return handle;
},
clearTimer(handle) {
if (handle && typeof handle === "object") {
handle.cleared = true;
cleared.push(handle.ms);
}
},
dgram: {
createSocket() {
class SlowSocket extends EventEmitter {
connect(_port, _host, callback) {
resolveConnectReady(callback);
}
close() {}
}
return new SlowSocket();
},
},
});
const pending = gate.ensureAccess({ hostname: "192.168.1.10", port: 22 });
const connectCallback = await connectReady;
// Simulate connect completing late in the safety window.
assert.equal(typeof connectCallback, "function");
assert.equal(safetyHandles.length, 1);
assert.ok(
safetyHandles[0].ms <= safetyMs && safetyHandles[0].ms >= safetyMs - 50,
`unexpected safety budget ${safetyHandles[0].ms}`,
);
connectCallback();
await pending;
assert.equal(safetyHandles[0].cleared, true);
assert.ok(
cleared.includes(safetyHandles[0].ms),
`safety timer should be cleared on connect, cleared=${JSON.stringify(cleared)}`,
);
assert.deepEqual(holds, [holdMs]);
});
test("createMacLocalNetworkAccessGate skips when main process already probed", async () => {
let creates = 0;
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
dgram: {
createSocket() {
creates += 1;
throw new Error("worker must not probe after main");
},
},
});
const result = await gate.ensureAccess({
hostname: "192.168.5.22",
port: 22,
_macLocalNetworkMainProbed: true,
});
assert.deepEqual(result, { skipped: true, reason: "main-probed" });
assert.equal(creates, 0);
});
test("createMacLocalNetworkAccessGate bounds hostname DNS lookup by the probe timeout", async () => {
let creates = 0;
const timeouts = [];
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probeTimeoutMs: 500,
probeHoldMs: 5,
setTimer: (fn, ms) => {
timeouts.push(ms);
queueMicrotask(fn);
return { ms };
},
clearTimer() {},
lookup: () => new Promise(() => {
// Never resolves - must be aborted by the probe timeout budget.
}),
dgram: {
createSocket() {
creates += 1;
throw new Error("must not probe after DNS timeout");
},
},
});
const result = await gate.ensureAccess({ hostname: "slow-dns.example", port: 22 });
assert.deepEqual(result, { skipped: true, reason: "not-local-network" });
assert.equal(creates, 0);
assert.ok(timeouts.includes(500), `expected DNS timeout arm, got ${JSON.stringify(timeouts)}`);
});
test("createMacLocalNetworkAccessGate carries resolved first-hop addresses into annotation", async () => {
const gate = createMacLocalNetworkAccessGate({
platform: "darwin",
forceElectron: true,
probeHoldMs: 0,
lookup: async () => ({ address: "192.168.1.20", family: 4 }),
dgram: {
createSocket() {
return createFakeUdpSocket();
},
},
});
const probe = await gate.ensureAccess({
jumpHosts: [{ hostname: "bastion.example.com", port: 22 }],
});
assert.equal(probe.hostname, "192.168.1.20");
assert.equal(gate.getResolvedFirstHop("bastion.example.com"), "192.168.1.20");
assert.match(
gate.annotateErrorMessage("connect EHOSTUNREACH 192.168.1.20:22", {
hostname: "app.example.com",
jumpHosts: [{ hostname: "bastion.example.com", port: 22 }],
}),
/Local Network/i,
);
});