mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-21 22:21:33 +00:00
fix(gateway): guard interface discovery failures
Closes #44180. Refs #47590. Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
@@ -360,6 +360,13 @@ describe("pickPrimaryLanIPv4", () => {
|
||||
vi.restoreAllMocks();
|
||||
}
|
||||
});
|
||||
|
||||
it("returns undefined when interface discovery throws", () => {
|
||||
vi.spyOn(os, "networkInterfaces").mockImplementation(() => {
|
||||
throw new Error("uv_interface_addresses failed");
|
||||
});
|
||||
expect(pickPrimaryLanIPv4()).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("isPrivateOrLoopbackAddress", () => {
|
||||
|
||||
@@ -15,7 +15,12 @@ import {
|
||||
* Prefers common interface names (en0, eth0) then falls back to any external IPv4.
|
||||
*/
|
||||
export function pickPrimaryLanIPv4(): string | undefined {
|
||||
const nets = os.networkInterfaces();
|
||||
let nets: ReturnType<typeof os.networkInterfaces>;
|
||||
try {
|
||||
nets = os.networkInterfaces();
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
const preferredNames = ["en0", "eth0"];
|
||||
for (const name of preferredNames) {
|
||||
const list = nets[name];
|
||||
|
||||
@@ -240,5 +240,13 @@ describe("infra runtime", () => {
|
||||
expect(out.ipv4).toEqual(["100.123.224.76"]);
|
||||
expect(out.ipv6).toEqual(["fd7a:115c:a1e0::8801:e04c"]);
|
||||
});
|
||||
|
||||
it("returns empty address lists when interface discovery throws", () => {
|
||||
vi.spyOn(os, "networkInterfaces").mockImplementation(() => {
|
||||
throw new Error("uv_interface_addresses failed");
|
||||
});
|
||||
|
||||
expect(listTailnetAddresses()).toEqual({ ipv4: [], ipv6: [] });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,7 +25,12 @@ export function listTailnetAddresses(): TailnetAddresses {
|
||||
const ipv4: string[] = [];
|
||||
const ipv6: string[] = [];
|
||||
|
||||
const ifaces = os.networkInterfaces();
|
||||
let ifaces: ReturnType<typeof os.networkInterfaces>;
|
||||
try {
|
||||
ifaces = os.networkInterfaces();
|
||||
} catch {
|
||||
return { ipv4, ipv6 };
|
||||
}
|
||||
for (const entries of Object.values(ifaces)) {
|
||||
if (!entries) {
|
||||
continue;
|
||||
|
||||
@@ -368,6 +368,27 @@ describe("pairing setup code", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a bind-specific error when interface discovery throws", async () => {
|
||||
const resolved = await resolvePairingSetupFromConfig(
|
||||
{
|
||||
gateway: {
|
||||
bind: "lan",
|
||||
auth: { mode: "token", token: "tok" },
|
||||
},
|
||||
},
|
||||
{
|
||||
networkInterfaces: () => {
|
||||
throw new Error("uv_interface_addresses failed");
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(resolved).toEqual({
|
||||
ok: false,
|
||||
error: "gateway.bind=lan set, but no private LAN IP was found.",
|
||||
});
|
||||
});
|
||||
|
||||
it("prefers gateway.remote.url over tailscale when requested", async () => {
|
||||
const runCommandWithTimeout = createTailnetDnsRunner();
|
||||
|
||||
|
||||
@@ -118,7 +118,12 @@ function pickIPv4Matching(
|
||||
networkInterfaces: () => ReturnType<typeof os.networkInterfaces>,
|
||||
matches: (address: string) => boolean,
|
||||
): string | null {
|
||||
const nets = networkInterfaces();
|
||||
let nets: ReturnType<typeof os.networkInterfaces>;
|
||||
try {
|
||||
nets = networkInterfaces();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
for (const entries of Object.values(nets)) {
|
||||
if (!entries) {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user