Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions sdk/typescript/examples/mix-fetch/browser/package.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"name": "@nymproject/mix-fetch-example-parcel",
"version": "1.0.6",
"version": "1.0.7",
"license": "Apache-2.0",
"scripts": {
"build": "parcel build --no-cache --no-content-hash",
"serve": "serve dist",
"start": "parcel --no-cache"
},
"dependencies": {
"@nymproject/mix-fetch": ">=1.4.2-rc.0 || ^1",
"@nymproject/mix-fetch": "^1.4.4",
"parcel": "^2.9.3"
},
"private": false,
"source": "src/index.html"
}
}
6 changes: 3 additions & 3 deletions sdk/typescript/packages/mix-fetch-node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nymproject/mix-fetch-node",
"version": "1.4.3",
"version": "1.4.4",
"description": "This package is a drop-in replacement for `fetch` in NodeJS to send HTTP requests over the Nym Mixnet.",
"license": "Apache-2.0",
"author": "Nym Technologies SA",
Expand Down Expand Up @@ -28,7 +28,7 @@
"tsc": "tsc --noEmit true"
},
"dependencies": {
"@nymproject/mix-fetch-wasm-node": ">=1.4.2-rc.0 || ^1",
"@nymproject/mix-fetch-wasm-node": "^1.4.4",
"comlink": "^4.3.1",
"fake-indexeddb": "^5.0.0",
"node-fetch": "^3.3.2",
Expand Down Expand Up @@ -68,4 +68,4 @@
},
"private": false,
"types": "./dist/cjs/index.d.ts"
}
}
4 changes: 2 additions & 2 deletions sdk/typescript/packages/mix-fetch/internal-dev/package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "@nymproject/mix-fetch-tester-webpack",
"version": "1.0.6",
"version": "1.0.7",
"license": "Apache-2.0",
"scripts": {
"build": "webpack build --progress --config webpack.prod.js",
"serve": "npx serve dist",
"start": "webpack serve --progress --port 3000"
},
"dependencies": {
"@nymproject/mix-fetch": ">=1.4.2-rc.0 || ^1"
"@nymproject/mix-fetch": ">=1.4.3-rc.0 || ^1"
},
"devDependencies": {
"@babel/core": "^7.22.10",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "@nymproject/mix-fetch-tester-parcel",
"version": "1.0.6",
"version": "1.0.7",
"license": "Apache-2.0",
"scripts": {
"build": "npx parcel build --no-cache --no-content-hash",
"serve": "npx serve dist",
"start": "npx parcel --no-cache"
},
"dependencies": {
"@nymproject/mix-fetch": ">=1.4.2-rc.0 || ^1"
"@nymproject/mix-fetch": ">=1.4.3-rc.0 || ^1"
},
"private": false,
"source": "../src/index.html"
Expand Down
6 changes: 3 additions & 3 deletions sdk/typescript/packages/mix-fetch/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nymproject/mix-fetch",
"version": "1.4.3",
"version": "1.4.4",
"description": "This package is a drop-in replacement for `fetch` to send HTTP requests over the Nym Mixnet.",
"license": "Apache-2.0",
"author": "Nym Technologies SA",
Expand Down Expand Up @@ -34,7 +34,7 @@
"tsc": "tsc --noEmit true"
},
"dependencies": {
"@nymproject/mix-fetch-wasm": ">=1.4.2-rc.0 || ^1",
"@nymproject/mix-fetch-wasm": "^1.4.4",
"comlink": "^4.3.1"
},
"devDependencies": {
Expand Down Expand Up @@ -82,4 +82,4 @@
"private": false,
"type": "module",
"types": "./dist/esm/index.d.ts"
}
}
2 changes: 1 addition & 1 deletion wasm/mix-fetch/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "mix-fetch-wasm"
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
version = "1.4.3"
version = "1.4.4"
edition = "2021"
keywords = ["nym", "fetch", "wasm", "webassembly", "privacy"]
license = "Apache-2.0"
Expand Down
6 changes: 4 additions & 2 deletions wasm/mix-fetch/go-mix-conn/internal/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ func (ar *CurrentActiveRequests) InjectData(id types.RequestId, data []byte) {
defer ar.Unlock()
_, exists := ar.Requests[id]
if !exists {
panic("attempted to write to connection that doesn't exist")
log.Error("attempted to inject data for connection %d that no longer exists — likely already cleaned up", id)
return
}
ar.Requests[id].injector.ServerData <- data
}
Expand All @@ -115,7 +116,8 @@ func (ar *CurrentActiveRequests) SendError(id types.RequestId, err error) {
defer ar.Unlock()
_, exists := ar.Requests[id]
if !exists {
panic("attempted to inject error data to connection that doesn't exist")
log.Error("attempted to inject error for connection %d that no longer exists — likely already cleaned up", id)
return
}
ar.Requests[id].injector.RemoteError <- err
}
Expand Down
190 changes: 116 additions & 74 deletions wasm/mix-fetch/internal-dev/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,100 +3,142 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Nym MixFetch Demo</title>
<title>Nym MixFetch Dev</title>
<script src="bootstrap.js"></script>
</head>

<body>
<h1>Mix Fetch Demo</h1>
<h1>MixFetch Dev</h1>

<fieldset id="startup-controls">
<legend>MixFetch Configuration</legend>
<p>
You can either use the default Gateway/NR combo run by us, or have
MixFetch choose a random one on startup.
</p>
<div style="margin-bottom: 10px">
<label>
<input type="radio" name="gateway-mode" value="default" checked />
Default Gateway (q2A2cbooyC16YJzvdYaSMH9X3cSiieZNtfBr8cE8Fi1)
</label>
<legend>Connection</legend>
<div>
<label><input type="radio" name="gateway-mode" value="default" checked />
Default Gateway (q2A2cbooyC16YJzvdYaSMH9X3cSiieZNtfBr8cE8Fi1)</label>
</div>
<div style="margin-bottom: 10px">
<label>
<input type="radio" name="gateway-mode" value="random" />
Random Gateway
</label>
<div>
<label><input type="radio" name="gateway-mode" value="random" />
Random Gateway</label>
</div>
<button id="start-mixfetch">Start MixFetch</button>
<span id="mixfetch-status" style="margin-left: 10px; color: gray"
>Not started</span
>
</fieldset>
<details style="margin-top: 8px">
<summary style="cursor: pointer; font-size: 0.9em; color: #555">Advanced Options</summary>
<div style="margin-top: 6px; padding: 8px; background: #f9f9f9; font-size: 0.9em">
<div>
<label><input type="checkbox" id="opt-force-tls" checked /> Force TLS</label>
</div>
<div style="margin-top: 4px">
<label>Client ID: <input type="text" id="opt-client-id" size="20" /></label>
<span style="font-size: 0.85em; color: #888">(randomised on load to avoid ID reuse)</span>
</div>
<div style="margin-top: 4px">
<label><input type="checkbox" id="opt-disable-poisson" checked /> Disable Poisson packet distribution</label>
</div>
<div style="margin-top: 4px">
<label><input type="checkbox" id="opt-disable-cover" checked /> Disable cover traffic</label>
</div>
<div style="margin-top: 4px">
<label>Request timeout (ms): <input type="number" id="opt-request-timeout" value="60000" min="1000" max="300000" style="width: 80px" /></label>
</div>
</div>
</details>

<hr />
<div style="margin-top: 8px">
<button id="start-mixfetch">Start MixFetch</button>
<span id="mixfetch-status" style="margin-left: 10px; color: gray">Not started</span>
</div>
</fieldset>

<fieldset id="fetch-controls" disabled>
<legend>Fetch Controls</legend>
<legend>Quick Fetch</legend>
<div>
<label>Target Host 1: </label>
<input
type="text"
size="60"
id="fetch_payload_1"
value="https://api.ipify.org?format=json"
/>
<button id="fetch-button-1">Fetch 1</button>
<input type="text" size="55" id="fetch_payload_1" value="https://api.ipify.org?format=json" />
<button id="fetch-button-1">GET</button>
</div>
<div>
<label>Target Host 2: </label>
<input
type="text"
size="60"
id="fetch_payload_2"
value="https://api6.ipify.org?format=json"
/>
<button id="fetch-button-2">Fetch 2</button>
<div style="margin-top: 4px">
<input type="text" size="55" id="fetch_payload_2" value="https://api6.ipify.org?format=json" />
<button id="fetch-button-2">GET</button>
</div>
<p>
Note: if you're hammering these endpoints and you start to get timeouts
(or you've been reloading the page a lot) then change the target hosts
to e.g. http://ipv4.icanhazip.com and https://ipv6.icanhazip.com/
</p>
<pre id="fetch-log" style="background: #f5f5f5; padding: 8px; margin-top: 8px; max-height: 150px; overflow-y: auto; font-size: 0.85em; white-space: pre-wrap; display: none"></pre>

<hr />

<h3>Stress Test</h3>
<div>
<button id="fetch-10-concurrent">
Send 10 Concurrent Requests (posts/1-10)
</button>
<p>
This does what is says on the tin - sends 10 fetch requests to
https://jsonplaceholder.typicode.com/posts/ 1 through 10
<label>Requests:</label>
<input type="number" id="stress-test-count" value="20" min="1" max="200" style="width: 60px" />
<label>Mode:</label>
<select id="stress-test-mode">
<option value="uniform">Uniform (same URL, incremented ID)</option>
<option value="mixed" selected>Mixed sizes</option>
<option value="drip">Slow drip (timeout boundary)</option>
</select>
</div>

<div id="stress-uniform-opts" style="display: none; margin-top: 8px; padding: 8px; background: #f9f9f9">
<div>
<label>Base URL:</label>
<input type="text" size="50" id="stress-test-url" value="https://jsonplaceholder.typicode.com/posts/" />
</div>
<p style="margin: 4px 0 0; font-size: 0.85em; color: #666">
Request ID (1..N) appended to the URL. All requests are the same size.
</p>
</div>
<hr />
<div>
<label>POST URL: </label>
<input
type="text"
size="60"
id="post_url"
value="https://jsonplaceholder.typicode.com/posts"
/>

<div id="stress-mixed-opts" style="margin-top: 8px; padding: 8px; background: #f9f9f9">
<p style="margin: 0 0 4px; font-size: 0.85em; color: #666">
Each request randomly assigned a size via <code>httpbin.org/bytes/{n}</code>.
Tests how the mixnet handles asymmetric payload sizes concurrently.
</p>
<table style="font-size: 0.9em; border-collapse: collapse">
<tr><td style="padding: 1px 10px 1px 0"><b>tiny</b></td><td>128 B</td></tr>
<tr><td style="padding: 1px 10px 1px 0"><b>small</b></td><td>1 KB</td></tr>
<tr><td style="padding: 1px 10px 1px 0"><b>medium</b></td><td>10 KB</td></tr>
<tr><td style="padding: 1px 10px 1px 0"><b>large</b></td><td>100 KB</td></tr>
<tr><td style="padding: 1px 10px 1px 0"><b>xlarge</b></td><td>1 MB</td></tr>
</table>
</div>
<div>
<label>POST Body (JSON): </label>
<textarea id="post_body" rows="3" cols="60">
{"title": "Test Post", "body": "Hello from MixFetch!", "userId": 1}</textarea
>

<div id="stress-drip-opts" style="display: none; margin-top: 8px; padding: 8px; background: #f9f9f9">
<p style="margin: 0 0 4px; font-size: 0.85em; color: #666">
Uses <code>httpbin.org/drip</code> to slowly drip bytes over a set duration,
keeping connections alive for a controlled time. Profiles are computed from
the Go timeout value below, so they always straddle the configured boundary
&mdash; some finish well before the timeout, others are mid-transfer when it fires.
</p>
<table style="font-size: 0.9em; border-collapse: collapse">
<tr>
<td style="padding: 1px 10px 1px 0"><b>safe</b></td>
<td>~50% of timeout</td>
<td style="padding-left: 10px; color: #666">well under the limit</td>
</tr>
<tr>
<td style="padding: 1px 10px 1px 0"><b>boundary</b></td>
<td>~92% of timeout</td>
<td style="padding-left: 10px; color: #666">server-side OK, but mixnet latency pushes it over</td>
</tr>
<tr>
<td style="padding: 1px 10px 1px 0"><b>over</b></td>
<td>~108% of timeout</td>
<td style="padding-left: 10px; color: #666">exceeds the timeout on its own</td>
</tr>
<tr>
<td style="padding: 1px 10px 1px 0"><b>slow-start</b></td>
<td>~17% delay + ~83% drip</td>
<td style="padding-left: 10px; color: #666">late first byte, then long transfer</td>
</tr>
</table>
</div>
<div>
<button id="post-button">Send POST Request</button>

<div style="margin-top: 8px">
<label>Go timeout (ms):</label>
<input type="number" id="stress-go-timeout" value="60000" min="500" max="120000" style="width: 80px" />
</div>
<p>Do a POST and get it echoed back</p>
</fieldset>

<hr />
<p>
<span id="output"></span>
</p>
<div style="margin-top: 8px">
<button id="stress-test-button">Run Stress Test</button>
<span id="stress-test-status" style="margin-left: 10px"></span>
</div>
<div id="stress-tracker" style="margin-top: 8px; font-family: monospace; font-size: 0.85em; display: none"></div>
</fieldset>
</body>
</html>
Loading
Loading