mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-06-24 07:29:56 +02:00
02328e59a2
Two independent root causes were producing auth failures on the upstream SOCKS5 dial path: 1. `url::Url::username()` / `Url::password()` return percent-encoded strings per the WHATWG URL spec, but the producer side already percent-encodes the credentials when assembling the upstream URL — so the upstream was receiving `%40` instead of `@` and authentication silently failed for any credential containing `@ : / + = % ! space` or non-ASCII characters. Centralize the decode in a new `upstream_userpass` helper and route all four upstream-dial sites through it (HTTP CONNECT → SOCKS5, HTTP CONNECT → HTTP Basic-Auth, local SOCKS5 → HTTP Basic-Auth, local SOCKS5 → SOCKS5). The Shadowsocks path already decoded manually and is unchanged. 2. async_socks5 0.6 issues a `write_u8` for every single-byte field of the SOCKS5 method-selection and RFC1929 sub-negotiation. On a raw `TcpStream` each call becomes its own TCP segment, and some upstream SOCKS5 implementations treat this fragmented submission as a misbehaving client and silently FIN instead of returning a status — curl with the same credentials succeeds because it buffers each sub-message into a single send(). Wrap the upstream socket in `tokio::io::BufStream` (the usage pattern the async_socks5 README shows) and enable TCP_NODELAY so flushes leave unsegmented. Includes unit tests covering percent-decode for ASCII / special-char / non-ASCII / no-credentials / username-only inputs, plus a trace-level SOCKS5 handshake byte logger that can be enabled with RUST_LOG=donutbrowser_lib::proxy_server=trace for future debugging.