mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
api.setConfig spread the new config over the old, so switching hosts carried the previous server's session token forward and the login request to the next server went out holding a live credential for the first one. The token is now dropped in the shared setConfig when host changes without an accompanying token, covering login, register and auto-connect at once. Also fixes a packaged-build-only failure: the CSP omitted blob: from img-src, so avatar upload validation (which measures the image via URL.createObjectURL) always failed in release and never in dev. Smaller connection and IPC fixes: ws_disconnect now bumps the connection generation instead of nulling the sender slot, so an in-flight handshake cannot install after a disconnect; a dead LiveKit proxy listener deregisters itself instead of being reused forever; httpProxy no longer caches an origin the Rust side may have torn down; logPersistence stopped looping on its own flush-failure logs; ConnectPage subscribes to transientError instead of reading it once; cert-mismatch accept/reject only act when the event host matches the live session. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
61 lines
2.3 KiB
TypeScript
61 lines
2.3 KiB
TypeScript
// Client-side helper for the Rust HTTP TOFU proxy (closes audit A-2026-07-02).
|
|
//
|
|
// The Rust `http_proxy` module runs one loopback TCP→TLS tunnel per remote
|
|
// host and pins the server certificate with the same trust-on-first-use store
|
|
// as the WebSocket proxy. REST calls go to http://127.0.0.1:{port} instead of
|
|
// https://{host} directly, so the webview never has to accept an invalid
|
|
// certificate and the bearer token never rides an unpinned TLS connection.
|
|
//
|
|
// This module maps a remote host ("host" or "host:port") to its loopback
|
|
// origin ("http://127.0.0.1:{port}"), caching per host and de-duplicating
|
|
// concurrent starts so parallel requests share one tunnel.
|
|
|
|
import { invoke } from "@tauri-apps/api/core";
|
|
import { createLogger } from "./logger";
|
|
|
|
const log = createLogger("http-proxy");
|
|
|
|
/** host → in-flight start so concurrent callers don't race the tunnel. */
|
|
const pending = new Map<string, Promise<string>>();
|
|
|
|
/**
|
|
* Ensure a tunnel exists for `host` and return its loopback origin
|
|
* (no trailing slash). Concurrency-safe per host.
|
|
*
|
|
* Always invokes start_http_proxy — never caches the resolved origin here.
|
|
* Only the Rust side knows whether its listener is still alive: after 5
|
|
* consecutive accept errors run_proxy_loop deregisters itself so the next
|
|
* start_http_proxy rebinds a fresh port (http_proxy.rs). A JS-side cache
|
|
* would keep pointing every REST call at that dead tunnel until app restart.
|
|
* The Rust reuse branch dedups an unchanged host cheaply, so the repeat
|
|
* invoke is inexpensive — mirroring livekitSession.ts's ensureLiveKitProxy.
|
|
*/
|
|
export async function ensureHttpProxy(host: string): Promise<string> {
|
|
const inFlight = pending.get(host);
|
|
if (inFlight) return inFlight;
|
|
|
|
const start = (async () => {
|
|
const port = await invoke<number>("start_http_proxy", { remoteHost: host });
|
|
const origin = `http://127.0.0.1:${port}`;
|
|
log.debug("tunnel ready", { host, origin });
|
|
return origin;
|
|
})();
|
|
|
|
pending.set(host, start);
|
|
try {
|
|
return await start;
|
|
} finally {
|
|
pending.delete(host);
|
|
}
|
|
}
|
|
|
|
/** Stop the tunnel for `host` (best-effort). */
|
|
export async function stopHttpProxy(host: string): Promise<void> {
|
|
pending.delete(host);
|
|
try {
|
|
await invoke("stop_http_proxy", { remoteHost: host });
|
|
} catch (err) {
|
|
log.debug("stop_http_proxy failed (ignored)", { host, error: String(err) });
|
|
}
|
|
}
|