43a1bd38e8
* Mod gitignore + license trimming + comment trimming
* Big rewrite
* SURB inputs + DNS button in internal-dev
* Make ipr addr optional
* Accidentatly omitted files from rewrite commit
* Makefile + readme
* Comment rewrite
* Optimisation comment
* Replace manual waker map with
smoltcp built-ins + adaptive poll
* Comments
* Extract socket creation helpers into stream.rs
* Cleanup comments
* Comment
* Comment notes and restrict ciphersuites wrt rustls-rustcrypto
* Dep. hack fix for demo + add clearnet fetch() for contrast
* Stripped down devtester
* Fix Clippy arg (fatfingered deletion)
* CodeRabbit catches
* Cargofmt
* Review nits: bridge logs, fetch early-return, static port counter, copyright years, README + Cargo + headless.js tidying
* PHONY + taskset override, switch internal-dev/tests to pnpm, fix wasm-pack out-dir
* Gate codec tests behind the codec feature for no-default-features builds
* IPv6 addr/route on smoltcp iface + configurable DNS resolvers via TunnelOpts
* DNS GUI inputs, close stale WS on reconnect, worker init guards + ws-send warning, Playwright listener cleanup, pnpm-lock in internal-dev
* Fix lp -> lp-data after rebase
* Revert nym-lp/nym-lp-data feature-gating left over from rebase
* Lift getrandom wasm_js cfg to workspace .cargo/config.toml so cargo check -p smolmix-wasm works from any CWD
* temp will amend git message
* Auto-discover IPR when none specified + 'Use random IPR' checkbox in internal-dev
* smolmix_tracker + State machine + ready_tunnel gate + getTunnelState JS surface
* Mirror red display() entries to console.error
* Add left out package-lock
* Reactor clock + yield_now + atomic seq + gateway-storage errors
* setupMixTunnel gate + MTU 1980 + http::Uri cleanup
* Review pass + fix test + clippy
* restore axum 0.8 bump from borked earlier merge
* Feature gating (dns/fetch/socket) + TunnelOptsBuilder + pnpm bypass
* Cont. with review comments
* tokio Nofity reactor wakes + cancellation + setup polishing
* Notify wakes + inner pattern + close_notify + util
* Tunable tunnelopts
* Fix tired commit
* CI prep
* Lint + Clippy
* coderabbit u32 fix
* nits + runtime debugging + expose in internal-dev
* remove redudant default-features
* Remove more redundant default-features
157 lines
4.0 KiB
JavaScript
157 lines
4.0 KiB
JavaScript
// smolmix-wasm Web Worker
|
|
//
|
|
// Loads the WASM module in a dedicated thread. All mixnet I/O
|
|
// (smoltcp polling, TLS crypto, DNS resolution, mixnet messaging)
|
|
// runs here, keeping the main thread responsive for UI rendering.
|
|
//
|
|
// Two communication channels:
|
|
// 1. Comlink — request/response for fetch (setupMixTunnel, mixFetch, disconnect)
|
|
// 2. Raw postMessage — bidirectional events for WebSocket (ws-connect, ws-send, ws-close)
|
|
//
|
|
// Comlink ignores messages without its internal UUID markers,
|
|
// so both channels coexist on the same Worker without conflicts.
|
|
|
|
import initWasm, {
|
|
setupMixTunnel as wasmSetup,
|
|
mixFetch as wasmFetch,
|
|
mixResolve as wasmResolve,
|
|
disconnectMixTunnel as wasmDisconnect,
|
|
mixSocket as wasmMixSocket,
|
|
wsSend as wasmWsSend,
|
|
wsClose as wasmWsClose,
|
|
setDebugLogging as wasmSetDebugLogging,
|
|
} from "smolmix-wasm";
|
|
import * as Comlink from "comlink";
|
|
|
|
let wasmReady = false;
|
|
|
|
// Comlink API (fetch)
|
|
|
|
const api = {
|
|
async setupMixTunnel(opts) {
|
|
if (!wasmReady) {
|
|
await initWasm();
|
|
wasmReady = true;
|
|
}
|
|
await wasmSetup(opts);
|
|
},
|
|
|
|
async mixFetch(url, init) {
|
|
if (!wasmReady) {
|
|
throw new Error("WASM not initialised; call setupMixTunnel first");
|
|
}
|
|
return await wasmFetch(url, init || {});
|
|
},
|
|
|
|
async mixResolve(hostname) {
|
|
if (!wasmReady) {
|
|
throw new Error("WASM not initialised; call setupMixTunnel first");
|
|
}
|
|
return await wasmResolve(hostname);
|
|
},
|
|
|
|
async disconnectMixTunnel() {
|
|
if (!wasmReady) {
|
|
throw new Error("WASM not initialised; call setupMixTunnel first");
|
|
}
|
|
await wasmDisconnect();
|
|
},
|
|
|
|
async setDebugLogging(enabled) {
|
|
if (!wasmReady) {
|
|
await initWasm();
|
|
wasmReady = true;
|
|
}
|
|
wasmSetDebugLogging(enabled);
|
|
},
|
|
};
|
|
|
|
Comlink.expose(api);
|
|
|
|
// Raw postMessage API (WebSocket)
|
|
|
|
// Maps main-thread connId → WASM handleId
|
|
const wsConnMap = new Map();
|
|
|
|
self.addEventListener("message", async (event) => {
|
|
const msg = event.data;
|
|
if (!msg || typeof msg.kind !== "string") return;
|
|
|
|
switch (msg.kind) {
|
|
case "ws-connect": {
|
|
if (!wasmReady) {
|
|
self.postMessage({
|
|
kind: "ws-event",
|
|
connId: msg.connId,
|
|
type: "error",
|
|
data: "WASM not initialised — call setupMixTunnel first",
|
|
});
|
|
return;
|
|
}
|
|
|
|
// WASM callback: fires for open/text/binary/close/error events.
|
|
// Captures connId so all events route to the correct MixSocket instance.
|
|
const onEvent = (handleId, type, data) => {
|
|
if (!wsConnMap.has(msg.connId)) {
|
|
wsConnMap.set(msg.connId, handleId);
|
|
}
|
|
self.postMessage({ kind: "ws-event", connId: msg.connId, type, data });
|
|
};
|
|
|
|
try {
|
|
await wasmMixSocket(msg.url, msg.protocols, onEvent);
|
|
} catch (e) {
|
|
console.error("[ws] connect failed:", e);
|
|
self.postMessage({
|
|
kind: "ws-event",
|
|
connId: msg.connId,
|
|
type: "error",
|
|
data: String(e),
|
|
});
|
|
}
|
|
break;
|
|
}
|
|
|
|
case "ws-send": {
|
|
const handleId = wsConnMap.get(msg.connId);
|
|
if (handleId == null) {
|
|
console.warn(`[ws] send for connId ${msg.connId} before connection ready`);
|
|
return;
|
|
}
|
|
try {
|
|
wasmWsSend(handleId, msg.payload);
|
|
} catch (e) {
|
|
self.postMessage({
|
|
kind: "ws-event",
|
|
connId: msg.connId,
|
|
type: "error",
|
|
data: String(e),
|
|
});
|
|
}
|
|
break;
|
|
}
|
|
|
|
case "ws-close": {
|
|
const handleId = wsConnMap.get(msg.connId);
|
|
if (handleId == null) {
|
|
console.warn(`[ws] close for connId ${msg.connId} before connection ready`);
|
|
return;
|
|
}
|
|
try {
|
|
wasmWsClose(handleId, msg.code || 1000, msg.reason || "");
|
|
} catch (e) {
|
|
self.postMessage({
|
|
kind: "ws-event",
|
|
connId: msg.connId,
|
|
type: "error",
|
|
data: String(e),
|
|
});
|
|
}
|
|
wsConnMap.delete(msg.connId);
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
|
|
self.postMessage({ kind: "Loaded" });
|