From 9f013aaab063f299ec26d407ab9c314824673d83 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Wed, 1 Apr 2026 12:18:55 +0100 Subject: [PATCH] Revert formatting changes to make PR less noisy --- wasm/mix-fetch/internal-dev/index.js | 536 +++++++++++++------------- wasm/mix-fetch/internal-dev/worker.js | 402 ++++++++++--------- 2 files changed, 467 insertions(+), 471 deletions(-) diff --git a/wasm/mix-fetch/internal-dev/index.js b/wasm/mix-fetch/internal-dev/index.js index 097ab041f4..988ce8966d 100644 --- a/wasm/mix-fetch/internal-dev/index.js +++ b/wasm/mix-fetch/internal-dev/index.js @@ -15,226 +15,226 @@ // ─── Worker client ────────────────────────────────────────────────────────── class WebWorkerClient { - worker = null; + worker = null; - constructor() { - this.worker = new Worker("./worker.js"); + constructor() { + this.worker = new Worker('./worker.js'); - this.worker.onmessage = (ev) => { - if (!ev.data || !ev.data.kind) return; - switch (ev.data.kind) { - case "DisplayString": - appendFetchLog(ev.data.args.rawString); - console.log("[mixfetch response]", ev.data.args.rawString); - break; - case "Log": { - const { message, level } = ev.data.args; - const fn = level === "error" ? console.error - : level === "warn" ? console.warn - : console.log; - fn(`[worker/${level}]`, message); - break; - } - case "MixFetchReady": - onMixFetchReady(); - break; - case "MixFetchError": - onMixFetchError(ev.data.args.error); - break; - case "StressTestFetchResult": - onStressTestFetchResult(ev.data.args); - break; - } - }; - } - - startMixFetch = (preferredGateway, setupOpts) => { - this.worker.postMessage({ kind: "StartMixFetch", args: { preferredGateway, setupOpts } }); - }; - - doFetch = (target) => { - this.worker.postMessage({ kind: "FetchPayload", args: { target } }); - }; - - setGoTimeout = (timeoutMs) => { - this.worker.postMessage({ kind: "SetGoTimeout", args: { timeoutMs } }); - }; - - doStressTest = (requests) => { - for (const req of requests) { - this.worker.postMessage({ - kind: "StressTestFetch", - args: { id: req.id, url: req.url, label: req.label }, - }); + this.worker.onmessage = (ev) => { + if (!ev.data || !ev.data.kind) return; + switch (ev.data.kind) { + case 'DisplayString': + appendFetchLog(ev.data.args.rawString); + console.log('[mixfetch response]', ev.data.args.rawString); + break; + case 'Log': { + const { message, level } = ev.data.args; + const fn = level === 'error' ? console.error + : level === 'warn' ? console.warn + : console.log; + fn(`[worker/${level}]`, message); + break; + } + case 'MixFetchReady': + onMixFetchReady(); + break; + case 'MixFetchError': + onMixFetchError(ev.data.args.error); + break; + case 'StressTestFetchResult': + onStressTestFetchResult(ev.data.args); + break; + } + }; } - }; + + startMixFetch = (preferredGateway, setupOpts) => { + this.worker.postMessage({ kind: 'StartMixFetch', args: { preferredGateway, setupOpts } }); + }; + + doFetch = (target) => { + this.worker.postMessage({ kind: 'FetchPayload', args: { target } }); + }; + + setGoTimeout = (timeoutMs) => { + this.worker.postMessage({ kind: 'SetGoTimeout', args: { timeoutMs } }); + }; + + doStressTest = (requests) => { + for (const req of requests) { + this.worker.postMessage({ + kind: 'StressTestFetch', + args: { id: req.id, url: req.url, label: req.label }, + }); + } + }; } // ─── Startup ──────────────────────────────────────────────────────────────── let client = null; -const DEFAULT_GATEWAY = "q2A2cbooyC16YJzvdYaSMH9X3cSiieZNtfBr8cE8Fi1"; +const DEFAULT_GATEWAY = 'q2A2cbooyC16YJzvdYaSMH9X3cSiieZNtfBr8cE8Fi1'; async function main() { - client = new WebWorkerClient(); + client = new WebWorkerClient(); - document.querySelector("#start-mixfetch").onclick = () => { - const gatewayMode = document.querySelector('input[name="gateway-mode"]:checked').value; - const preferredGateway = gatewayMode === "default" ? DEFAULT_GATEWAY : undefined; + document.querySelector('#start-mixfetch').onclick = () => { + const gatewayMode = document.querySelector('input[name="gateway-mode"]:checked').value; + const preferredGateway = gatewayMode === 'default' ? DEFAULT_GATEWAY : undefined; - const setupOpts = { - forceTls: document.getElementById("opt-force-tls").checked, - clientId: document.getElementById("opt-client-id").value, - disablePoisson: document.getElementById("opt-disable-poisson").checked, - disableCover: document.getElementById("opt-disable-cover").checked, - requestTimeoutMs: parseInt(document.getElementById("opt-request-timeout").value, 10), + const setupOpts = { + forceTls: document.getElementById('opt-force-tls').checked, + clientId: document.getElementById('opt-client-id').value, + disablePoisson: document.getElementById('opt-disable-poisson').checked, + disableCover: document.getElementById('opt-disable-cover').checked, + requestTimeoutMs: parseInt(document.getElementById('opt-request-timeout').value, 10), + }; + + document.querySelector('#start-mixfetch').disabled = true; + document.querySelectorAll('input[name="gateway-mode"]').forEach((r) => (r.disabled = true)); + updateStatus('mixfetch-status', 'Starting...', 'orange'); + + // Sync the stress-test Go timeout to match the configured request timeout + document.getElementById('stress-go-timeout').value = setupOpts.requestTimeoutMs; + + console.log(`Starting MixFetch (${gatewayMode} gateway${preferredGateway ? `: ${preferredGateway}` : ''})...`); + console.log('Setup options:', setupOpts); + client.startMixFetch(preferredGateway, setupOpts); }; - document.querySelector("#start-mixfetch").disabled = true; - document.querySelectorAll('input[name="gateway-mode"]').forEach((r) => (r.disabled = true)); - updateStatus("mixfetch-status", "Starting...", "orange"); + document.querySelector('#fetch-button-1').onclick = () => doFetch(1); + document.querySelector('#fetch-button-2').onclick = () => doFetch(2); - // Sync the stress-test Go timeout to match the configured request timeout - document.getElementById("stress-go-timeout").value = setupOpts.requestTimeoutMs; - - console.log(`Starting MixFetch (${gatewayMode} gateway${preferredGateway ? `: ${preferredGateway}` : ""})...`); - console.log("Setup options:", setupOpts); - client.startMixFetch(preferredGateway, setupOpts); - }; - - document.querySelector("#fetch-button-1").onclick = () => doFetch(1); - document.querySelector("#fetch-button-2").onclick = () => doFetch(2); - - const stressModeSelect = document.getElementById("stress-test-mode"); - stressModeSelect.onchange = function () { - document.getElementById("stress-uniform-opts").style.display = this.value === "uniform" ? "block" : "none"; - document.getElementById("stress-mixed-opts").style.display = this.value === "mixed" ? "block" : "none"; - document.getElementById("stress-drip-opts").style.display = this.value === "drip" ? "block" : "none"; - }; - - document.querySelector("#stress-test-button").onclick = () => { - const count = parseInt(document.getElementById("stress-test-count").value, 10); - const mode = document.getElementById("stress-test-mode").value; - const goTimeoutMs = parseInt(document.getElementById("stress-go-timeout").value, 10); - - document.querySelector("#stress-test-button").disabled = true; - updateStatus("stress-test-status", "Running...", "orange"); - client.setGoTimeout(goTimeoutMs); - - const requests = generateStressRequests(count, mode, goTimeoutMs); - stressTest = { - count, - mode, - startTime: performance.now(), - results: [], - completionOrder: [], - profiles: {}, + const stressModeSelect = document.getElementById('stress-test-mode'); + stressModeSelect.onchange = function () { + document.getElementById('stress-uniform-opts').style.display = this.value === 'uniform' ? 'block' : 'none'; + document.getElementById('stress-mixed-opts').style.display = this.value === 'mixed' ? 'block' : 'none'; + document.getElementById('stress-drip-opts').style.display = this.value === 'drip' ? 'block' : 'none'; }; - for (const req of requests) { - stressTest.profiles[req.id] = { label: req.label, bytes: req.bytes }; - } - initStressTracker(requests); + document.querySelector('#stress-test-button').onclick = () => { + const count = parseInt(document.getElementById('stress-test-count').value, 10); + const mode = document.getElementById('stress-test-mode').value; + const goTimeoutMs = parseInt(document.getElementById('stress-go-timeout').value, 10); - console.log(`%c=== STRESS TEST: ${count} requests, ${mode} mode, timeout=${goTimeoutMs}ms ===`, "font-weight: bold"); + document.querySelector('#stress-test-button').disabled = true; + updateStatus('stress-test-status', 'Running...', 'orange'); + client.setGoTimeout(goTimeoutMs); - if (mode === "mixed" || mode === "drip") { - const breakdown = {}; - for (const req of requests) breakdown[req.label] = (breakdown[req.label] || 0) + 1; - console.log("Profiles:", breakdown); - } + const requests = generateStressRequests(count, mode, goTimeoutMs); + stressTest = { + count, + mode, + startTime: performance.now(), + results: [], + completionOrder: [], + profiles: {}, + }; + for (const req of requests) { + stressTest.profiles[req.id] = { label: req.label, bytes: req.bytes }; + } - client.doStressTest(requests); - }; + initStressTracker(requests); + + console.log(`%c=== STRESS TEST: ${count} requests, ${mode} mode, timeout=${goTimeoutMs}ms ===`, 'font-weight: bold'); + + if (mode === 'mixed' || mode === 'drip') { + const breakdown = {}; + for (const req of requests) breakdown[req.label] = (breakdown[req.label] || 0) + 1; + console.log('Profiles:', breakdown); + } + + client.doStressTest(requests); + }; } // ─── UI helpers ───────────────────────────────────────────────────────────── function updateStatus(elementId, text, color) { - const el = document.getElementById(elementId); - el.textContent = text; - el.style.color = color; + const el = document.getElementById(elementId); + el.textContent = text; + el.style.color = color; } function onMixFetchReady() { - updateStatus("mixfetch-status", "Ready", "green"); - document.getElementById("fetch-controls").disabled = false; - console.log("%cMixFetch ready!", "color: green; font-weight: bold"); + updateStatus('mixfetch-status', 'Ready', 'green'); + document.getElementById('fetch-controls').disabled = false; + console.log('%cMixFetch ready!', 'color: green; font-weight: bold'); } function onMixFetchError(error) { - updateStatus("mixfetch-status", "Error: " + error, "red"); - document.querySelector("#start-mixfetch").disabled = false; - document.querySelectorAll('input[name="gateway-mode"]').forEach((r) => (r.disabled = false)); - console.error("MixFetch error:", error); + updateStatus('mixfetch-status', 'Error: ' + error, 'red'); + document.querySelector('#start-mixfetch').disabled = false; + document.querySelectorAll('input[name="gateway-mode"]').forEach((r) => (r.disabled = false)); + console.error('MixFetch error:', error); } // ─── Quick fetch ──────────────────────────────────────────────────────────── function appendFetchLog(text) { - const log = document.getElementById("fetch-log"); - log.style.display = "block"; - const ts = new Date().toISOString().substr(11, 12); - log.textContent += `${ts} ${text}\n`; - log.scrollTop = log.scrollHeight; + const log = document.getElementById('fetch-log'); + log.style.display = 'block'; + const ts = new Date().toISOString().substr(11, 12); + log.textContent += `${ts} ${text}\n`; + log.scrollTop = log.scrollHeight; } async function doFetch(id) { - const url = document.getElementById(`fetch_payload_${id}`).value; - appendFetchLog(`GET ${url}`); - console.log(`GET ${url}`); - await client.doFetch(url); + const url = document.getElementById(`fetch_payload_${id}`).value; + appendFetchLog(`GET ${url}`); + console.log(`GET ${url}`); + await client.doFetch(url); } // ─── Stress test ──────────────────────────────────────────────────────────── const STRESS_PROFILES = [ - { label: "tiny", bytes: 128 }, - { label: "small", bytes: 1024 }, - { label: "medium", bytes: 10240 }, - { label: "large", bytes: 102400 }, - { label: "xlarge", bytes: 1048576 }, + { label: 'tiny', bytes: 128 }, + { label: 'small', bytes: 1024 }, + { label: 'medium', bytes: 10240 }, + { label: 'large', bytes: 102400 }, + { label: 'xlarge', bytes: 1048576 }, ]; function buildDripProfiles(timeoutSec) { - return [ - { label: "safe", dripDuration: Math.round(timeoutSec * 0.50), dripDelay: 0, dripBytes: 100 }, - { label: "boundary", dripDuration: Math.round(timeoutSec * 0.92), dripDelay: 0, dripBytes: 100 }, - { label: "over", dripDuration: Math.round(timeoutSec * 1.08), dripDelay: 0, dripBytes: 100 }, - { label: "slow-start", dripDuration: Math.round(timeoutSec * 0.83), dripDelay: Math.round(timeoutSec * 0.17), dripBytes: 100 }, - ]; + return [ + { label: 'safe', dripDuration: Math.round(timeoutSec * 0.50), dripDelay: 0, dripBytes: 100 }, + { label: 'boundary', dripDuration: Math.round(timeoutSec * 0.92), dripDelay: 0, dripBytes: 100 }, + { label: 'over', dripDuration: Math.round(timeoutSec * 1.08), dripDelay: 0, dripBytes: 100 }, + { label: 'slow-start', dripDuration: Math.round(timeoutSec * 0.83), dripDelay: Math.round(timeoutSec * 0.17), dripBytes: 100 }, + ]; } function generateStressRequests(count, mode, timeoutMs) { - const requests = []; - if (mode === "uniform") { - const baseUrl = document.getElementById("stress-test-url").value; - for (let i = 1; i <= count; i++) { - requests.push({ id: i, url: `${baseUrl}${i}`, label: "uniform", bytes: null }); + const requests = []; + if (mode === 'uniform') { + const baseUrl = document.getElementById('stress-test-url').value; + for (let i = 1; i <= count; i++) { + requests.push({ id: i, url: `${baseUrl}${i}`, label: 'uniform', bytes: null }); + } + } else if (mode === 'drip') { + const dripProfiles = buildDripProfiles(timeoutMs / 1000); + for (let i = 1; i <= count; i++) { + const p = dripProfiles[Math.floor(Math.random() * dripProfiles.length)]; + requests.push({ + id: i, + url: `https://httpbin.org/drip?duration=${p.dripDuration}&numbytes=${p.dripBytes}&delay=${p.dripDelay}&code=200`, + label: p.label, + bytes: p.dripBytes, + }); + } + } else { + for (let i = 1; i <= count; i++) { + const p = STRESS_PROFILES[Math.floor(Math.random() * STRESS_PROFILES.length)]; + requests.push({ + id: i, + url: `https://httpbin.org/bytes/${p.bytes}`, + label: p.label, + bytes: p.bytes, + }); + } } - } else if (mode === "drip") { - const dripProfiles = buildDripProfiles(timeoutMs / 1000); - for (let i = 1; i <= count; i++) { - const p = dripProfiles[Math.floor(Math.random() * dripProfiles.length)]; - requests.push({ - id: i, - url: `https://httpbin.org/drip?duration=${p.dripDuration}&numbytes=${p.dripBytes}&delay=${p.dripDelay}&code=200`, - label: p.label, - bytes: p.dripBytes, - }); - } - } else { - for (let i = 1; i <= count; i++) { - const p = STRESS_PROFILES[Math.floor(Math.random() * STRESS_PROFILES.length)]; - requests.push({ - id: i, - url: `https://httpbin.org/bytes/${p.bytes}`, - label: p.label, - bytes: p.bytes, - }); - } - } - return requests; + return requests; } let stressTest = null; @@ -243,125 +243,125 @@ let stressTest = null; let trackerData = {}; function initStressTracker(requests) { - const tracker = document.getElementById("stress-tracker"); - tracker.style.display = "block"; - trackerData = {}; + const tracker = document.getElementById('stress-tracker'); + tracker.style.display = 'block'; + trackerData = {}; - // Count how many of each profile were sent - for (const req of requests) { - if (!trackerData[req.label]) { - trackerData[req.label] = { sent: 0, ok: 0, fail: 0, times: [] }; + // Count how many of each profile were sent + for (const req of requests) { + if (!trackerData[req.label]) { + trackerData[req.label] = { sent: 0, ok: 0, fail: 0, times: [] }; + } + trackerData[req.label].sent++; } - trackerData[req.label].sent++; - } - renderTracker(); + renderTracker(); } function renderTracker() { - const tracker = document.getElementById("stress-tracker"); - const rows = Object.entries(trackerData).map(([label, d]) => { - const pending = d.sent - d.ok - d.fail; - const avg = d.times.length > 0 - ? (d.times.reduce((a, b) => a + b, 0) / d.times.length).toFixed(1) + "s" - : "-"; - const max = d.times.length > 0 ? Math.max(...d.times).toFixed(1) + "s" : "-"; - const min = d.times.length > 0 ? Math.min(...d.times).toFixed(1) + "s" : "-"; + const tracker = document.getElementById('stress-tracker'); + const rows = Object.entries(trackerData).map(([label, d]) => { + const pending = d.sent - d.ok - d.fail; + const avg = d.times.length > 0 + ? (d.times.reduce((a, b) => a + b, 0) / d.times.length).toFixed(1) + 's' + : '-'; + const max = d.times.length > 0 ? Math.max(...d.times).toFixed(1) + 's' : '-'; + const min = d.times.length > 0 ? Math.min(...d.times).toFixed(1) + 's' : '-'; - let status = ""; - if (d.ok > 0) status += `${d.ok} ok`; - if (d.fail > 0) status += `${status ? " " : ""}${d.fail} fail`; - if (pending > 0) status += `${status ? " " : ""}${pending} pending`; + let status = ''; + if (d.ok > 0) status += `${d.ok} ok`; + if (d.fail > 0) status += `${status ? ' ' : ''}${d.fail} fail`; + if (pending > 0) status += `${status ? ' ' : ''}${pending} pending`; - let timing = ""; - if (d.times.length > 0) { - timing = `avg ${avg} / min ${min} / max ${max}`; - } + let timing = ''; + if (d.times.length > 0) { + timing = `avg ${avg} / min ${min} / max ${max}`; + } - return ` - ${label} - ${d.sent} - ${status} - ${timing} - `; - }); + return ` + ${label} + ${d.sent} + ${status} + ${timing} + `; + }); - tracker.innerHTML = ` - - - - - - - ${rows.join("")} -
profilesentstatustiming
`; + tracker.innerHTML = ` + + + + + + + ${rows.join('')} +
profilesentstatustiming
`; } function onStressTestFetchResult(result) { - if (!stressTest) return; + if (!stressTest) return; - const profile = stressTest.profiles[result.id]; - result.label = profile ? profile.label : "?"; + const profile = stressTest.profiles[result.id]; + result.label = profile ? profile.label : '?'; - stressTest.results.push(result); - stressTest.completionOrder.push(result.id); + stressTest.results.push(result); + stressTest.completionOrder.push(result.id); + + // Update tracker + const td = trackerData[result.label]; + if (td) { + if (result.ok) { + td.ok++; + td.times.push(parseFloat(result.elapsed)); + } else { + td.fail++; + } + renderTracker(); + } + + const progress = `${stressTest.results.length}/${stressTest.count}`; + const tag = `#${result.id} ${result.label}`; - // Update tracker - const td = trackerData[result.label]; - if (td) { if (result.ok) { - td.ok++; - td.times.push(parseFloat(result.elapsed)); + console.log(`%c[${tag}] ${result.status} OK ${result.elapsed}s ${result.textLength}B (${progress})`, 'color: green'); } else { - td.fail++; - } - renderTracker(); - } - - const progress = `${stressTest.results.length}/${stressTest.count}`; - const tag = `#${result.id} ${result.label}`; - - if (result.ok) { - console.log(`%c[${tag}] ${result.status} OK ${result.elapsed}s ${result.textLength}B (${progress})`, "color: green"); - } else { - console.error(`[${tag}] FAIL ${result.elapsed}s ${result.error} (${progress})`); - } - - updateStatus("stress-test-status", progress, "orange"); - - // Summary on completion - if (stressTest.results.length === stressTest.count) { - const totalElapsed = ((performance.now() - stressTest.startTime) / 1000).toFixed(2); - const succeeded = stressTest.results.filter((r) => r.ok).length; - const failed = stressTest.results.filter((r) => !r.ok).length; - - console.log(`%c=== COMPLETE: ${totalElapsed}s | OK ${succeeded}/${stressTest.count} | Failed ${failed}/${stressTest.count} ===`, "font-weight: bold"); - console.log("Completion order:", stressTest.completionOrder); - - // Per-profile breakdown in console - const profileLabels = Object.keys(trackerData); - const profileList = profileLabels.map((label) => ({ label })); - if (stressTest.mode === "mixed" || stressTest.mode === "drip") { - const table = []; - for (const profile of profileList) { - const matching = stressTest.results.filter((r) => r.label === profile.label); - if (matching.length === 0) continue; - const ok = matching.filter((r) => r.ok).length; - const times = matching.filter((r) => r.ok).map((r) => parseFloat(r.elapsed)); - const avg = times.length > 0 ? (times.reduce((a, b) => a + b, 0) / times.length).toFixed(2) : "-"; - const max = times.length > 0 ? Math.max(...times).toFixed(2) : "-"; - table.push({ profile: profile.label, ok: `${ok}/${matching.length}`, avg: `${avg}s`, max: `${max}s` }); - } - console.table(table); + console.error(`[${tag}] FAIL ${result.elapsed}s ${result.error} (${progress})`); } - updateStatus("stress-test-status", - `Done: ${succeeded}/${stressTest.count} OK, ${failed} failed (${totalElapsed}s)`, - failed > 0 ? "red" : "green" - ); - document.querySelector("#stress-test-button").disabled = false; - stressTest = null; - } + updateStatus('stress-test-status', progress, 'orange'); + + // Summary on completion + if (stressTest.results.length === stressTest.count) { + const totalElapsed = ((performance.now() - stressTest.startTime) / 1000).toFixed(2); + const succeeded = stressTest.results.filter((r) => r.ok).length; + const failed = stressTest.results.filter((r) => !r.ok).length; + + console.log(`%c=== COMPLETE: ${totalElapsed}s | OK ${succeeded}/${stressTest.count} | Failed ${failed}/${stressTest.count} ===`, 'font-weight: bold'); + console.log('Completion order:', stressTest.completionOrder); + + // Per-profile breakdown in console + const profileLabels = Object.keys(trackerData); + const profileList = profileLabels.map((label) => ({ label })); + if (stressTest.mode === 'mixed' || stressTest.mode === 'drip') { + const table = []; + for (const profile of profileList) { + const matching = stressTest.results.filter((r) => r.label === profile.label); + if (matching.length === 0) continue; + const ok = matching.filter((r) => r.ok).length; + const times = matching.filter((r) => r.ok).map((r) => parseFloat(r.elapsed)); + const avg = times.length > 0 ? (times.reduce((a, b) => a + b, 0) / times.length).toFixed(2) : '-'; + const max = times.length > 0 ? Math.max(...times).toFixed(2) : '-'; + table.push({ profile: profile.label, ok: `${ok}/${matching.length}`, avg: `${avg}s`, max: `${max}s` }); + } + console.table(table); + } + + updateStatus('stress-test-status', + `Done: ${succeeded}/${stressTest.count} OK, ${failed} failed (${totalElapsed}s)`, + failed > 0 ? 'red' : 'green' + ); + document.querySelector('#stress-test-button').disabled = false; + stressTest = null; + } } main(); diff --git a/wasm/mix-fetch/internal-dev/worker.js b/wasm/mix-fetch/internal-dev/worker.js index 01868a178a..c747299f54 100644 --- a/wasm/mix-fetch/internal-dev/worker.js +++ b/wasm/mix-fetch/internal-dev/worker.js @@ -15,28 +15,28 @@ const RUST_WASM_URL = "mix_fetch_wasm_bg.wasm"; const GO_WASM_URL = "go_conn.wasm"; -importScripts("mix_fetch_wasm.js"); -importScripts("wasm_exec.js"); +importScripts('mix_fetch_wasm.js'); +importScripts('wasm_exec.js'); -console.log("Initializing worker"); +console.log('Initializing worker'); // wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts` const { - default_debug, - no_cover_debug, - NymClient, - set_panic_hook, - Config, - GatewayEndpointConfig, - ClientStorage, - MixFetchConfig, - send_client_data, - start_new_mixnet_connection, - setupMixFetch, - disconnectMixFetch, - setupMixFetchWithConfig, - mix_fetch_initialised, - finish_mixnet_connection, + default_debug, + no_cover_debug, + NymClient, + set_panic_hook, + Config, + GatewayEndpointConfig, + ClientStorage, + MixFetchConfig, + send_client_data, + start_new_mixnet_connection, + setupMixFetch, + disconnectMixFetch, + setupMixFetchWithConfig, + mix_fetch_initialised, + finish_mixnet_connection, } = wasm_bindgen; let client = null; @@ -45,43 +45,43 @@ const go = new Go(); // Defined in wasm_exec.js var goWasm; let mixFetchReady = false; -function sendLog(message, level = "info") { - self.postMessage({ - kind: "Log", - args: { message, level }, - }); +function sendLog(message, level = 'info') { + self.postMessage({ + kind: 'Log', + args: { message, level }, + }); } function sendReady() { - self.postMessage({ kind: "MixFetchReady" }); + self.postMessage({ kind: 'MixFetchReady' }); } function sendError(error) { - self.postMessage({ - kind: "MixFetchError", - args: { error: String(error) }, - }); + self.postMessage({ + kind: 'MixFetchError', + args: { error: String(error) }, + }); } async function logFetchResult(res) { - console.log(res); - let text = await res.text(); - console.log("HEADERS: ", ...res.headers); - console.log("STATUS: ", res.status); - console.log("STATUS TEXT: ", res.statusText); - console.log("OK: ", res.ok); - console.log("TYPE: ", res.type); - console.log("URL: ", res.url); - console.log("BODYUSED: ", res.bodyUsed); - console.log("REDIRECTED: ", res.redirected); - console.log("TEXT: ", text); + console.log(res); + let text = await res.text(); + console.log("HEADERS: ", ...res.headers); + console.log("STATUS: ", res.status); + console.log("STATUS TEXT: ", res.statusText); + console.log("OK: ", res.ok); + console.log("TYPE: ", res.type); + console.log("URL: ", res.url); + console.log("BODYUSED: ", res.bodyUsed); + console.log("REDIRECTED: ", res.redirected); + console.log("TEXT: ", text); - self.postMessage({ - kind: "DisplayString", - args: { - rawString: text, - }, - }); + self.postMessage({ + kind: 'DisplayString', + args: { + rawString: text, + }, + }); } /* @@ -110,205 +110,201 @@ async function logFetchResult(res) { */ async function nativeSetup(preferredGateway, setupOpts = {}) { - sendLog("Setting up MixFetch..."); - if (preferredGateway) { - sendLog(`Using preferred gateway: ${preferredGateway}`); - } else { - sendLog("Using random gateway selection"); - } + sendLog('Setting up MixFetch...'); + if (preferredGateway) { + sendLog(`Using preferred gateway: ${preferredGateway}`); + } else { + sendLog('Using random gateway selection'); + } - const { - forceTls = true, - clientId = "my-client", - disablePoisson = true, - disableCover = true, - requestTimeoutMs = 60000, - } = setupOpts; + const { + forceTls = true, + clientId = 'my-client', + disablePoisson = true, + disableCover = true, + requestTimeoutMs = 60000, + } = setupOpts; - const noCoverTrafficOverride = { - traffic: { disableMainPoissonPacketDistribution: disablePoisson }, - coverTraffic: { disableLoopCoverTrafficStream: disableCover }, - }; - const mixFetchOverride = { - requestTimeoutMs, - }; + const noCoverTrafficOverride = { + traffic: { disableMainPoissonPacketDistribution: disablePoisson }, + coverTraffic: { disableLoopCoverTrafficStream: disableCover }, + }; + const mixFetchOverride = { + requestTimeoutMs, + }; - const opts = { - forceTls, - clientId, - clientOverride: noCoverTrafficOverride, - mixFetchOverride, - }; + const opts = { + forceTls, + clientId, + clientOverride: noCoverTrafficOverride, + mixFetchOverride, + }; - if (preferredGateway) { - opts.preferredGateway = preferredGateway; - } + if (preferredGateway) { + opts.preferredGateway = preferredGateway; + } - sendLog( - `Setup config: forceTls=${forceTls}, clientId=${clientId}, disablePoisson=${disablePoisson}, disableCover=${disableCover}, timeout=${requestTimeoutMs}ms` - ); - sendLog("Calling setupMixFetch..."); - await setupMixFetch(opts); - sendLog("setupMixFetch completed"); + sendLog( + `Setup config: forceTls=${forceTls}, clientId=${clientId}, disablePoisson=${disablePoisson}, disableCover=${disableCover}, timeout=${requestTimeoutMs}ms` + ); + sendLog('Calling setupMixFetch...'); + await setupMixFetch(opts); + sendLog('setupMixFetch completed'); } async function startMixFetch(preferredGateway, setupOpts) { - sendLog("Instantiating MixFetch..."); + sendLog('Instantiating MixFetch...'); - try { - await nativeSetup(preferredGateway, setupOpts); - mixFetchReady = true; - sendLog("MixFetch client running!"); - sendReady(); - } catch (e) { - sendLog("Failed to start MixFetch: " + e, "error"); - sendError(e); - } + try { + await nativeSetup(preferredGateway, setupOpts); + mixFetchReady = true; + sendLog('MixFetch client running!'); + sendReady(); + } catch (e) { + sendLog('Failed to start MixFetch: ' + e, 'error'); + sendError(e); + } } async function handleFetchPayload(target) { - if (!mixFetchReady) { - sendLog("MixFetch not ready yet", "error"); - return; - } + if (!mixFetchReady) { + sendLog('MixFetch not ready yet', 'error'); + return; + } - const url = target; - const args = { mode: "unsafe-ignore-cors" }; + const url = target; + const args = { mode: "unsafe-ignore-cors" }; - try { - sendLog(`Fetching: ${url}`); - const mixFetchRes = await mixFetch(url, args); - sendLog("Fetch completed"); - await logFetchResult(mixFetchRes); - } catch (e) { - sendLog("Fetch request failure: " + e, "error"); - console.error("mix fetch request failure: ", e); - } + try { + sendLog(`Fetching: ${url}`); + const mixFetchRes = await mixFetch(url, args); + sendLog('Fetch completed'); + await logFetchResult(mixFetchRes); + } catch (e) { + sendLog('Fetch request failure: ' + e, 'error'); + console.error("mix fetch request failure: ", e); + } } async function handleStressTestFetch(id, url, label) { - if (!mixFetchReady) { - sendLog("MixFetch not ready yet", "error"); - return; - } + if (!mixFetchReady) { + sendLog('MixFetch not ready yet', 'error'); + return; + } - const tag = `[stress #${id} ${label}]`; - const start = performance.now(); - const args = { mode: "unsafe-ignore-cors" }; + const tag = `[stress #${id} ${label}]`; + const start = performance.now(); + const args = { mode: "unsafe-ignore-cors" }; - try { - sendLog(`${tag} Fetching: ${url}`); - const res = await mixFetch(url, args); - const text = await res.text(); - const elapsed = ((performance.now() - start) / 1000).toFixed(2); - sendLog(`${tag} ${res.status} OK in ${elapsed}s (${text.length} bytes)`); - self.postMessage({ - kind: "StressTestFetchResult", - args: { - id, - ok: true, - status: res.status, - elapsed, - textLength: text.length, - body: text, - }, - }); - } catch (e) { - const elapsed = ((performance.now() - start) / 1000).toFixed(2); - sendLog(`${tag} FAILED in ${elapsed}s: ${e}`, "error"); - self.postMessage({ - kind: "StressTestFetchResult", - args: { id, ok: false, elapsed, error: String(e) }, - }); - } + try { + sendLog(`${tag} Fetching: ${url}`); + const res = await mixFetch(url, args); + const text = await res.text(); + const elapsed = ((performance.now() - start) / 1000).toFixed(2); + sendLog(`${tag} ${res.status} OK in ${elapsed}s (${text.length} bytes)`); + self.postMessage({ + kind: 'StressTestFetchResult', + args: { + id, + ok: true, + status: res.status, + elapsed, + textLength: text.length, + body: text, + }, + }); + } catch (e) { + const elapsed = ((performance.now() - start) / 1000).toFixed(2); + sendLog(`${tag} FAILED in ${elapsed}s: ${e}`, 'error'); + self.postMessage({ + kind: 'StressTestFetchResult', + args: { id, ok: false, elapsed, error: String(e) }, + }); + } } function setupMessageHandler() { - self.onmessage = async (event) => { - if (event.data && event.data.kind) { - switch (event.data.kind) { - case "StartMixFetch": { - const { preferredGateway, setupOpts } = event.data.args; - await startMixFetch(preferredGateway, setupOpts); - break; + self.onmessage = async (event) => { + if (event.data && event.data.kind) { + switch (event.data.kind) { + case 'StartMixFetch': { + const { preferredGateway, setupOpts } = event.data.args; + await startMixFetch(preferredGateway, setupOpts); + break; + } + case 'FetchPayload': { + const { target } = event.data.args; + await handleFetchPayload(target); + break; + } + case 'SetGoTimeout': { + const { timeoutMs } = event.data.args; + sendLog(`Setting Go-side request timeout to ${timeoutMs}ms`); + self.__go_rs_bridge__.goWasmSetMixFetchRequestTimeout(timeoutMs); + break; + } + case 'StressTestFetch': { + const { id, url, label } = event.data.args; + // NOT awaited — each request runs independently, + // just like separate callers in a real app + handleStressTestFetch(id, url, label); + break; + } + } } - case "FetchPayload": { - const { target } = event.data.args; - await handleFetchPayload(target); - break; - } - case "SetGoTimeout": { - const { timeoutMs } = event.data.args; - sendLog(`Setting Go-side request timeout to ${timeoutMs}ms`); - self.__go_rs_bridge__.goWasmSetMixFetchRequestTimeout(timeoutMs); - break; - } - case "StressTestFetch": { - const { id, url, label } = event.data.args; - // NOT awaited — each request runs independently, - // just like separate callers in a real app - handleStressTestFetch(id, url, label); - break; - } - } - } - }; + }; } // TODO: look into https://www.aaron-powell.com/posts/2019-02-08-golang-wasm-5-compiling-with-webpack/ async function loadGoWasm() { - const resp = await fetch(GO_WASM_URL); + const resp = await fetch(GO_WASM_URL); - if ("instantiateStreaming" in WebAssembly) { - const wasmObj = await WebAssembly.instantiateStreaming( - resp, - go.importObject - ); - goWasm = wasmObj.instance; - go.run(goWasm); - } else { - const bytes = await resp.arrayBuffer(); - const wasmObj = await WebAssembly.instantiate(bytes, go.importObject); - goWasm = wasmObj.instance; - go.run(goWasm); - } + if ('instantiateStreaming' in WebAssembly) { + const wasmObj = await WebAssembly.instantiateStreaming(resp, go.importObject); + goWasm = wasmObj.instance; + go.run(goWasm); + } else { + const bytes = await resp.arrayBuffer(); + const wasmObj = await WebAssembly.instantiate(bytes, go.importObject); + goWasm = wasmObj.instance; + go.run(goWasm); + } } function setupRsGoBridge() { - // (note: reason for intermediate `__rs_go_bridge__` object is to decrease global scope bloat - // and to discourage users from trying to call those methods directly) - self.__rs_go_bridge__ = {}; - self.__rs_go_bridge__.send_client_data = send_client_data; - self.__rs_go_bridge__.start_new_mixnet_connection = - start_new_mixnet_connection; - self.__rs_go_bridge__.mix_fetch_initialised = mix_fetch_initialised; - self.__rs_go_bridge__.finish_mixnet_connection = finish_mixnet_connection; + // (note: reason for intermediate `__rs_go_bridge__` object is to decrease global scope bloat + // and to discourage users from trying to call those methods directly) + self.__rs_go_bridge__ = {}; + self.__rs_go_bridge__.send_client_data = send_client_data; + self.__rs_go_bridge__.start_new_mixnet_connection = start_new_mixnet_connection; + self.__rs_go_bridge__.mix_fetch_initialised = mix_fetch_initialised; + self.__rs_go_bridge__.finish_mixnet_connection = finish_mixnet_connection; } async function main() { - sendLog("Worker starting..."); + sendLog('Worker starting...'); - // load rust WASM package - sendLog("Loading Rust WASM..."); - await wasm_bindgen(RUST_WASM_URL); - sendLog("Loaded Rust WASM"); + // load rust WASM package + sendLog('Loading Rust WASM...'); + await wasm_bindgen(RUST_WASM_URL); + sendLog('Loaded Rust WASM'); - // load go WASM package - sendLog("Loading Go WASM..."); - await loadGoWasm(); - sendLog("Loaded Go WASM"); + // load go WASM package + sendLog('Loading Go WASM...'); + await loadGoWasm(); + sendLog('Loaded Go WASM'); - // sets up better stack traces in case of in-rust panics - set_panic_hook(); + // sets up better stack traces in case of in-rust panics + set_panic_hook(); - setupRsGoBridge(); + setupRsGoBridge(); - goWasmSetLogging("trace"); + goWasmSetLogging("trace"); - // Set up message handler (MixFetch will be started on demand) - setupMessageHandler(); + // Set up message handler (MixFetch will be started on demand) + setupMessageHandler(); - sendLog("Worker ready - click Start MixFetch to begin"); + sendLog('Worker ready - click Start MixFetch to begin'); } // Let's get started!