The plan's share feature for the (single-config) desktop GUI. The QR is
rendered locally so the access key never leaves the device.
- src-tauri: add `qrcode = "0.14"` (features=["svg"]) + `generate_qr`
command (string -> SVG), registered in the invoke handler. Ported from
the current ostp-gui. (cargo check on src-tauri passes.)
- Frontend: "Share" button next to Import builds `ostp://KEY@HOST?sni&type`
from the current config fields, calls generate_qr, and shows a modal with
the QR + a read-only link + Copy. Added i18n keys (en/ru) so the new
data-i18n labels resolve (missing keys would render as the raw key).
Note: Rust side verified via cargo check; the frontend is syntax-checked
(node --check) but not runtime-verified — needs a Tauri build to confirm
visually.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When using xhttp (UoT) mode on Android, the underlying TcpStream was
not protected with VpnService.protect(fd). This caused the TCP connection
to be routed back into the TUN interface, creating an infinite routing
loop and failing the connection immediately.
Added Android-specific socket protection to the TcpStream in connect_xhttp.
This fixes xhttp/UoT mode on mobile networks.
The core bug: server sent 5 TLS records in server_hello but client only
read the first one (ServerHello), then passed remaining bytes (CCS + fake
records) into RealityStream. RealityStream saw 0x14 (CCS) != 0x17 and
immediately returned an error, killing the connection.
Changes:
- reality.rs: append ChangeCipherSpec after ClientHello (RFC 8446 D.4)
export REALITY_SERVER_HANDSHAKE_RECORDS=5 constant
- xhttp.rs: drain all 5 server handshake records before creating RealityStream
- uot.rs: rebuild server_hello as proper 5-record TLS 1.3 flight:
ServerHello + CCS + fake EE (108B) + fake Cert (812B) + fake Fin (52B)
drain client CCS from raw stream before wrapping in RealityStream