mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
fix: handle IPv6 loopback (::1) in LiveKit URL resolution
The previous implementation used serverHost.split(":")[0] to extract
the hostname, which fails for IPv6 addresses — "::1:7880".split(":")[0]
yields "" instead of "::1". Now handles three formats:
- Bracketed: [::1]:7880 → host = "::1"
- Bare IPv6: ::1 → host = "::1" (multiple colons detected)
- IPv4/hostname: example.com:443 → host = "example.com"
Also fixes ensureLiveKitProxy to wrap bare IPv6 in brackets and
correctly detect port presence in bracketed notation.
This commit is contained in:
@@ -281,7 +281,17 @@ export class LiveKitSession {
|
||||
|
||||
private async resolveLiveKitUrl(proxyPath: string, directUrl?: string): Promise<string> {
|
||||
if (this.serverHost !== null) {
|
||||
const host = this.serverHost.split(":")[0] ?? "";
|
||||
// Extract hostname, handling IPv6 bracket notation (e.g. "[::1]:7880")
|
||||
// and bare IPv6 (e.g. "::1").
|
||||
let host: string;
|
||||
if (this.serverHost.startsWith("[")) {
|
||||
host = this.serverHost.slice(1, this.serverHost.indexOf("]"));
|
||||
} else if ((this.serverHost.match(/:/g) ?? []).length > 1) {
|
||||
// Bare IPv6 address (multiple colons, no brackets) — use as-is
|
||||
host = this.serverHost;
|
||||
} else {
|
||||
host = this.serverHost.split(":")[0] ?? "";
|
||||
}
|
||||
const isLocal = host === "localhost" || host === "127.0.0.1" || host === "::1";
|
||||
if (isLocal && directUrl) {
|
||||
log.debug("LiveKit URL resolved via direct (local)", { url: directUrl });
|
||||
@@ -310,7 +320,17 @@ export class LiveKitSession {
|
||||
// Ensure host:port format — default to 443 (standard HTTPS) when the
|
||||
// server is behind a reverse proxy. Without an explicit port, the Rust
|
||||
// proxy would default to 8443 which may not be exposed.
|
||||
const hostWithPort = this.serverHost.includes(":") ? this.serverHost : `${this.serverHost}:443`;
|
||||
// Handle IPv6: "[::1]:7880" has port, "[::1]" and bare "::1" do not.
|
||||
let hostWithPort: string;
|
||||
if (this.serverHost.startsWith("[")) {
|
||||
// Bracketed IPv6 — check for "]:port" suffix
|
||||
hostWithPort = this.serverHost.includes("]:") ? this.serverHost : `${this.serverHost}:443`;
|
||||
} else if ((this.serverHost.match(/:/g) ?? []).length > 1) {
|
||||
// Bare IPv6 (multiple colons) — wrap in brackets and add default port
|
||||
hostWithPort = `[${this.serverHost}]:443`;
|
||||
} else {
|
||||
hostWithPort = this.serverHost.includes(":") ? this.serverHost : `${this.serverHost}:443`;
|
||||
}
|
||||
this.liveKitProxyPort = await invoke<number>("start_livekit_proxy", {
|
||||
remoteHost: hostWithPort,
|
||||
});
|
||||
|
||||
@@ -1378,27 +1378,18 @@ describe("LiveKitSession", () => {
|
||||
expect(url).toBe("ws://127.0.0.1:7880/livekit");
|
||||
});
|
||||
|
||||
it("returns directUrl when serverHost is ::1 (no port)", async () => {
|
||||
// serverHost "::1" splits on ":" to ["", "", "1"], [0] is "" — NOT "::1".
|
||||
// So ::1 is only detected as local when the host part equals "::1",
|
||||
// which requires serverHost to have no port (split(":")[0] === "").
|
||||
// This test documents that ::1 with port is NOT detected as local.
|
||||
it("returns directUrl when serverHost is bare ::1", async () => {
|
||||
session.setServerHost("::1");
|
||||
const url = await (session as any).resolveLiveKitUrl("/livekit", "ws://[::1]:7880/livekit");
|
||||
// split(":")[0] of "::1" is "" which does not match "::1", so it falls through.
|
||||
// This means ::1 is effectively NOT handled as local by the current implementation.
|
||||
// The proxy path kicks in instead.
|
||||
expect(url).toBe("ws://127.0.0.1:7881/livekit");
|
||||
// Bare IPv6 with multiple colons — detected as local, returns directUrl
|
||||
expect(url).toBe("ws://[::1]:7880/livekit");
|
||||
});
|
||||
|
||||
it("treats ::1 with port as non-local and routes through proxy", async () => {
|
||||
session.setServerHost("::1:7880");
|
||||
it("returns directUrl when serverHost is bracketed [::1]:7880", async () => {
|
||||
session.setServerHost("[::1]:7880");
|
||||
const url = await (session as any).resolveLiveKitUrl("/livekit", "ws://[::1]:7880/livekit");
|
||||
// split(":")[0] of "::1:7880" is "" — not matched as local
|
||||
expect(mockInvoke).toHaveBeenCalledWith("start_livekit_proxy", {
|
||||
remoteHost: "::1:7880",
|
||||
});
|
||||
expect(url).toBe("ws://127.0.0.1:7881/livekit");
|
||||
// Bracketed IPv6 — host extracted as "::1", detected as local
|
||||
expect(url).toBe("ws://[::1]:7880/livekit");
|
||||
});
|
||||
|
||||
it("calls ensureLiveKitProxy and returns proxy URL for remote host with slash path", async () => {
|
||||
|
||||
Reference in New Issue
Block a user