103 lines
5.7 KiB
Markdown
103 lines
5.7 KiB
Markdown
# MTProxy core module
|
|
|
|
Self-contained MTProxy/FakeTLS policy engine. Lives at `jni/mtproxy` and
|
|
builds as its own CMake static library, `mtproxy_core` (see
|
|
`jni/CMakeLists.txt`): it depends only on BoringSSL and PUBLIC-exports
|
|
`jni/`, so consumers include it as `"mtproxy/MtProxyX.h"`. The socket/Java
|
|
layers link against it; it never links back — the dependency arrow points
|
|
one way, into the engine.
|
|
|
|
Pure logic: phase classification, endpoint/adaptive/recovery policy, the
|
|
single retry-hold authority, handshake planning and scheduling, secret
|
|
parsing, server-flight parsing, startup timeline, probe coordination,
|
|
terminal-diagnostic derivation, failure evidence.
|
|
|
|
`MtProxyClientHelloPolicy` also owns the pre-send FakeTLS relay contract:
|
|
517..4096-byte structural bounds, a 32-byte session id, TLS 1.3 as the
|
|
first real cipher after relay-shaped GREASE, exact SNI equality with the
|
|
`ee` secret, and the measured-safe effective profile (Yandex by default;
|
|
exact Chromium-shaped profiles are withheld).
|
|
|
|
## Boundary rules (enforced by `Tools/check_mtproxy_module_boundary.py`)
|
|
|
|
- Files here may include only other `mtproxy/` headers — zero tgnet
|
|
headers (the `MT_PROXY_STARTUP_*` handshake limits live in
|
|
`MtProxyOptions.h`, not `Defines.h`).
|
|
- System/third-party includes are whitelisted (`ALLOWED_SYSTEM` in the
|
|
checker); the same surface is stubbed in `Tools/mtproxy_host_stubs`,
|
|
so the module compiles standalone on the host:
|
|
`python Tools/build_mtproxy_host.py` (MSVC Build Tools; also part of
|
|
`check_mtproxy_all.py`). Extend whitelist and stubs together.
|
|
- No sockets, no `FileLog`, no `ConnectionsManager`, no JNI. I/O and
|
|
logging stay in `ConnectionSocket`/`Connection`; this module only
|
|
decides, it never performs.
|
|
- `MtProxyPhaseClassification.h` is AUTOGENERATED from
|
|
`Tools/mtproxy_phase_contract.py` (single source of truth shared with
|
|
Java's `ProxyPhaseClassification.java`). Never edit by hand; run
|
|
`Tools/generate_mtproxy_phase_classification.py` after contract changes.
|
|
|
|
## Migration roadmap (one owner at a time)
|
|
|
|
1. **Done:** phase/verdict classification generated from one contract
|
|
(C++ + Java from `Tools/mtproxy_phase_contract.py`).
|
|
2. **Done:** module extracted into this folder with an enforced
|
|
dependency boundary; zero project includes; host build
|
|
(`Tools/build_mtproxy_host.py`) compiles it standalone.
|
|
3. **Done (decision layer):** classification decisions moved into the
|
|
module and host-compiled: `MtProxyTerminalDiagnostic` (terminal close
|
|
verdict derivation), generated `isLocalSchedulerTimeout` (was a hand
|
|
strcmp list in ConnectionSocket). The FakeTLS wire-state structs stay
|
|
with the I/O owner (`ConnectionSocketStateMachine`) by design: the
|
|
module decides, the socket performs.
|
|
4. **Done:** `MtProxyRetryAuthority` is the single owner of
|
|
"how long until the next attempt": Connection's exponential reconnect
|
|
backoff, the endpoint-cooldown/scheduler-pacing merge and the probe
|
|
coordinator hold all converge there.
|
|
`check_mtproxy_connection_pattern_modes.py` forbids hold math
|
|
re-growing in Connection/ConnectionSocket.
|
|
5. **Done (classification ownership):** Java's `ProxyPhasePolicy.classify`
|
|
table (kind/keyScope/backoff/rotate) is generated from the contract
|
|
(`java_key_scope`/`java_backoff` overrides document the two historical
|
|
divergences); checkers assert `mtproxy_phase_contract.java_policy()`
|
|
instead of parsing the Java switch.
|
|
|
|
6. **Done (JNI hold bridge):** the native retry-authority hold rides the
|
|
`onProxyConnectionStageChanged` callback as `suggestedReconnectHoldMs`
|
|
(Defines delegate → TgNetWrapper JNI → `ProxyConnectionEvent`). When it
|
|
is non-zero, `ProxyHealthStore.rememberEndpointFailure` uses it verbatim
|
|
(`hold_source=native`) instead of re-deriving from its own clock; the
|
|
local clock survives only for Java-origin failures with no native hold
|
|
(invalid-secret config failures keep their longer local floor). Native
|
|
raises the cooldown into the hold before the event leaves
|
|
`publishProxyConnectionStage`.
|
|
7. **Done (module promotion):** this folder moved from `tgnet/mtproxy` to
|
|
`jni/mtproxy` and became the `mtproxy_core` CMake static library.
|
|
|
|
8. **Done (host-run unit tests):** `Tools/build_mtproxy_host.py` now links
|
|
the module objects with `Tools/mtproxy_host_tests/mtproxy_host_tests.cpp`
|
|
and RUNS the binary as part of `check_mtproxy_all.py`. Covered: retry-hold
|
|
computation (base/cap/coordinator-merge envelopes), terminal-diagnostic
|
|
derivation (pre-I/O preservation, errno split, timeline fallback) and the
|
|
generated skip-list invariants, the ClientHello relay contract and the
|
|
effective-profile withholding policy. The RAND_bytes stub is a deterministic
|
|
xorshift stream — never all-zero (rejection sampling would spin forever)
|
|
and never asserted exactly (tests use jitter envelopes).
|
|
|
|
9. **Done (scheduler is a pure executor):** the sweep-style
|
|
`enqueueStale` API was removed outright — background check sweeps are
|
|
now impossible by construction, not just forbidden by guards. Checks
|
|
are explicit (`enqueueNow` from the UI); per-endpoint cadence is the
|
|
native hold via `ProxyHealthStore.nextCheckTime` →
|
|
`nextAllowedCheckTime`; the only timing the scheduler owns is
|
|
`PROXY_CHECK_SPACING_MS` start-to-start smoothing of its single-active
|
|
queue (submission hygiene, not a retry clock — documented in code and
|
|
enforced: `check_proxy_check_scheduler.py` forbids `failureBackoffMs`/
|
|
`cooldownMs` math in the scheduler and requires the
|
|
`nextAllowedCheckTime` gate). The foreground live-ping interval in
|
|
`ProxyListActivity` is a deliberate UI-freshness setting, not a retry
|
|
clock.
|
|
|
|
## Next iterations
|
|
|
|
- Device build/test remains the gate for the Java/JNI changes (no local
|
|
NDK or javac verification).
|