Extract MTProxy endpoint recording logic into MtProxyEndpointRecorder and MtProxyProbeLease helper classes, and introduce EmojiPanelAnimationScheduler for controlled animation playback in emoji panels. Key changes: - Move endpoint failure/handshake/data-path recording from ConnectionSocket to MtProxyEndpointRecorder - Replace probe lease management methods with MtProxyProbeLease member class - Add EmojiPanelAnimationScheduler to manage GIF/sticker playback based on visibility and scroll state - Add animation FPS limiting and invalidation delegate hooks to ImageReceiver - Update Java proxy event handling to route connected/connect_start/usable_success through ProxyEventReducer - Update verification tools to reflect new architecture
94 lines
4.5 KiB
C++
94 lines
4.5 KiB
C++
// AUTOGENERATED by Tools/generate_mtproxy_phase_classification.py - DO NOT EDIT.
|
|
// Source of truth: Tools/mtproxy_phase_contract.py. After editing the contract
|
|
// run the generator; check_mtproxy_all.py fails while this file is stale.
|
|
#ifndef MTPROXYPHASECLASSIFICATION_H
|
|
#define MTPROXYPHASECLASSIFICATION_H
|
|
|
|
#include <string.h>
|
|
|
|
namespace MtProxyPhase {
|
|
|
|
// Terminal verdicts that can be assigned before the socket performs any
|
|
// real I/O (secret validation, DNS verdict caches, probe-coordinator
|
|
// backoff decisions). deriveMtProxyTerminalDiagnostic must preserve these
|
|
// across closeSocket: re-deriving from the startup timeline would replace
|
|
// them with "connection_not_started", which is on the local-scheduler
|
|
// skip list, so neither endpoint cooldown nor reconnect backoff would
|
|
// engage and connect() would hot-loop.
|
|
inline bool isPreIoTerminalVerdict(const char *phase) {
|
|
if (phase == nullptr) {
|
|
return false;
|
|
}
|
|
return strcmp(phase, "dns_negative_cache_hit") == 0
|
|
|| strcmp(phase, "dns_blocked_zero_address") == 0
|
|
|| strcmp(phase, "secret_parse_invalid_domain_control_char") == 0
|
|
|| strcmp(phase, "secret_parse_invalid_domain") == 0
|
|
|| strcmp(phase, "faketls_not_mtproxy_response") == 0
|
|
|| strcmp(phase, "faketls_no_server_hello_terminal") == 0
|
|
|| strcmp(phase, "faketls_server_closed_terminal") == 0
|
|
|| strcmp(phase, "handshake_profiles_exhausted") == 0;
|
|
}
|
|
|
|
// Failure verdicts that must hold the next reconnect attempt
|
|
// (Connection::onDisconnectedInternal exponential backoff).
|
|
inline bool needsReconnectBackoff(const char *phase) {
|
|
if (phase == nullptr) {
|
|
return false;
|
|
}
|
|
return strcmp(phase, "host_resolve_failed") == 0
|
|
|| strcmp(phase, "host_resolve_timeout") == 0
|
|
|| strcmp(phase, "tcp_not_connected") == 0
|
|
|| strcmp(phase, "tcp_connection_refused") == 0
|
|
|| strcmp(phase, "tcp_connect_timeout") == 0
|
|
|| strcmp(phase, "tcp_connected_no_pong") == 0
|
|
|| strcmp(phase, "secret_parse_invalid_domain_control_char") == 0
|
|
|| strcmp(phase, "secret_parse_invalid_domain") == 0
|
|
|| strcmp(phase, "faketls_not_mtproxy_response") == 0
|
|
|| strcmp(phase, "faketls_no_server_hello_terminal") == 0
|
|
|| strcmp(phase, "faketls_server_closed_terminal") == 0
|
|
|| strcmp(phase, "handshake_profiles_exhausted") == 0
|
|
|| strcmp(phase, "mtproxy_packet_sent_no_response") == 0
|
|
|| strcmp(phase, "post_handshake_no_appdata") == 0
|
|
|| strcmp(phase, "dropped_early_after_appdata") == 0;
|
|
}
|
|
|
|
// Phases published through the MtProxySocketObservation facade
|
|
// (mtProxySocketObservationIsHighRiskPhase): failures that must record
|
|
// an endpoint failure at close, plus the data-path success markers
|
|
// routed the same way.
|
|
inline bool isObservationFacadePhase(const char *phase) {
|
|
if (phase == nullptr) {
|
|
return false;
|
|
}
|
|
return strcmp(phase, "first_tls_app_recv") == 0
|
|
|| strcmp(phase, "first_mtproxy_packet_recv") == 0
|
|
|| strcmp(phase, "dns_blocked_zero_address") == 0
|
|
|| strcmp(phase, "secret_parse_invalid_domain_control_char") == 0
|
|
|| strcmp(phase, "secret_parse_invalid_domain") == 0
|
|
|| strcmp(phase, "faketls_not_mtproxy_response") == 0
|
|
|| strcmp(phase, "faketls_no_server_hello_terminal") == 0
|
|
|| strcmp(phase, "faketls_server_closed_terminal") == 0
|
|
|| strcmp(phase, "handshake_profiles_exhausted") == 0
|
|
|| strcmp(phase, "post_handshake_no_appdata") == 0
|
|
|| strcmp(phase, "recipe_failed") == 0;
|
|
}
|
|
|
|
// Local scheduler/gate timeouts: the wait was produced by our own
|
|
// pre-TCP machinery (admission queue, endpoint cooldown, gates), not
|
|
// by the network. MtProxyEndpointRecorder::recordFailure skips these so a local
|
|
// wake-up never counts as an endpoint failure. Deliberately excludes
|
|
// mtproxy_probe_wait_timeout and includes background_handshake_aborted.
|
|
inline bool isLocalSchedulerTimeout(const char *phase) {
|
|
if (phase == nullptr) {
|
|
return false;
|
|
}
|
|
return strcmp(phase, "connection_not_started") == 0
|
|
|| strcmp(phase, "admission_timeout") == 0
|
|
|| strcmp(phase, "endpoint_cooldown_timeout") == 0
|
|
|| strcmp(phase, "dns_coalesce_timeout") == 0
|
|
|| strcmp(phase, "tcp_connect_gate_timeout") == 0
|
|
|| strcmp(phase, "background_handshake_aborted") == 0;
|
|
}
|
|
}
|
|
|
|
#endif
|