Files
MasterHttpRelayVPN-RUST/Cargo.toml
T
therealaleph 75401acf0c fix: v1.8.5 — tunnel-node caps TCP drain at 16 MiB to stay under Apps Script body ceiling
@bankbunk reported (#460) that on a 1 Gbps VPS, raw MP4 streams in Full
mode died with `batch JSON parse error: EOF while parsing a string at
line 1 column 52428685` minutes into playback. Root cause: drain_now
took the entire per-session read buffer in one shot. On high-bandwidth
VPS the reader task fills the buffer with tens of MiB between polls;
the resulting batch response (raw + base64 1.33× + JSON envelope)
exceeded Apps Script's ~50 MiB hard cap; Apps Script truncated mid-base64;
the client's serde_json parse hit EOF and the stream tore.

Fix: drain_now now returns at most TCP_DRAIN_MAX_BYTES (16 MiB) per call
and leaves the tail in the buffer for the next poll. EOF is held back
until the buffer is fully drained so partial drains don't tear the
session prematurely. Three regression tests cover the cap, the under-cap
pass-through, and the EOF-holdback case (33 tunnel-node tests passing).

@bankbunk's wondershaper rate-limit workaround (40 Mbps cap on the VPS
interface) is no longer necessary — high-bandwidth VPS users can run at
line rate again.
2026-04-29 06:28:17 +03:00

113 lines
4.2 KiB
TOML

[package]
name = "mhrv-rs"
version = "1.8.5"
edition = "2021"
description = "Rust port of MasterHttpRelayVPN -- DPI bypass via Google Apps Script relay with domain fronting"
license = "MIT"
[lib]
name = "mhrv_rs"
path = "src/lib.rs"
# `cdylib` lets the Android app dlopen libmhrv_rs.so via System.loadLibrary.
# `rlib` keeps the desktop binaries linking normally — same .rlib is used
# for `mhrv-rs` and `mhrv-rs-ui` builds on macOS/Linux/Windows.
crate-type = ["rlib", "cdylib"]
[[bin]]
name = "mhrv-rs"
path = "src/main.rs"
[[bin]]
name = "mhrv-rs-ui"
path = "src/bin/ui.rs"
required-features = ["ui"]
[features]
default = []
ui = ["dep:eframe"]
[dependencies]
tokio = { version = "1", features = ["rt-multi-thread", "macros", "net", "time", "io-util", "signal", "sync"] }
tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12"] }
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] }
rustls-pemfile = "2"
webpki-roots = "0.26"
rcgen = { version = "0.13", features = ["x509-parser"] }
rustls-pki-types = "1"
time = "0.3"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
thiserror = "2"
base64 = "0.22"
bytes = "1"
httparse = "1"
rand = "0.8"
h2 = "0.4"
http = "1"
flate2 = "1"
directories = "5"
futures-util = { version = "0.3", default-features = false, features = ["std"] }
# 64-bit atomics on 32-bit MIPS/ARMv5 targets. Rust's std AtomicU64 is
# only available on targets that expose native 64-bit atomics, which
# mipsel-unknown-linux-musl does not — `AtomicU64` resolves to "no
# such name in sync::atomic" and the whole crate fails to build. The
# `fallback` feature uses a global spinlock when the target can't do
# 64-bit atomically; on x86_64 / aarch64 / armv7 / etc. it compiles
# down to the native instructions with no overhead.
portable-atomic = { version = "1", features = ["fallback"] }
# Optional UI dep: only pulled in when --features ui is set.
# Both `glow` (OpenGL 2+) and `wgpu` (DX12/Vulkan/Metal) are compiled in;
# the binary picks one at startup — glow by default for compat with the
# egui look-and-feel we've been shipping, but falls back to wgpu when
# `MHRV_RENDERER=wgpu` is set. Issue #28: users on older Windows
# hardware / RDP / VMs without OpenGL 2.0 crash with
# `egui_glow requires opengl 2.0+` — the wgpu backend uses DX12/Vulkan
# instead and covers those boxes.
eframe = { version = "0.28", default-features = false, features = [
"default_fonts",
"glow",
"wgpu",
"persistence",
], optional = true }
url = "2.5.8"
# Unix-only deps. Must come after `[dependencies]` because starting a new
# table here otherwise ends the main one — anything below it (incl. eframe)
# would end up scoped to cfg(unix) and disappear on Windows builds.
# libc is referenced for the RLIMIT_NOFILE bump (issue #8 — OpenWRT routers
# ship a very low fd limit that fills up fast under browser load). Already
# pulled in transitively via tokio, so zero new weight.
[target.'cfg(unix)'.dependencies]
libc = "0.2"
# Android-only deps: jni gives us the extern "system" wrappers used in
# src/android_jni.rs; zero cost on any other platform because the whole
# module is `#[cfg(target_os = "android")]`.
#
# tun2proxy is the TUN <-> SOCKS5 bridge — it reads raw IP packets from the
# fd VpnService hands us, runs a userspace TCP/IP stack (smoltcp under the
# hood), and funnels every TCP/UDP flow through our local SOCKS5. Without
# this, VpnService establishes a TUN device nothing reads from and all
# traffic black-holes (symptom: Chrome shows DNS_PROBE_STARTED).
[target.'cfg(target_os = "android")'.dependencies]
jni = { version = "0.21", default-features = false }
tun2proxy = { version = "0.7", default-features = false, features = ["udpgw"] }
[dev-dependencies]
# Used in mitm tests to sanity-check the cert extensions we emit.
x509-parser = "0.16"
# `test-util` enables `tokio::test(start_paused = true)` so timing-
# sensitive tests in `tunnel_client` (the empty-poll cadence) can
# auto-advance virtual time instead of burning real wall-clock seconds.
tokio = { version = "1", features = ["test-util"] }
[profile.release]
panic = "abort"
codegen-units = 1
lto = true
opt-level = 3
strip = true