mirror of
https://github.com/by-sonic/tglock.git
synced 2026-09-05 18:16:09 +03:00
fix: диагностика перестаёт врать — падения маршрутов и потеря секрета (#38)
Два дефекта одного класса: состояние, которое не отражает реальность. Оба найдены по данным из #32 и #37. #32. Присланный лог показывал «сбоев 0» при том, что DC2 и DC4 всегда шли через «Запасной Telegram IP», а DC203 всегда через «Системный DNS» — то есть основные закреплённые адреса не использовались ни разу. Причина в счётчике: ws_failures растёт только когда упали ВСЕ маршруты и соединение не состоялось. Падения отдельных маршрутов через record_failure не попадали никуда, поэтому перебор с откатом на запасной адрес выглядел как полное отсутствие проблем. Добавлен route_failures: растёт на каждое падение маршрута, виден в строке статуса CLI и в диагностике интерфейса. Теперь по логу сразу видно, что закреплённый адрес мёртв, а не приходится это выводить. #37. Симптом: Telegram пишет «прокси настроен неверно и будет отключён», при этом Check status показывает Available. Это картина несовпадения секрета: TCP проходит, init не разбирается под другим секретом, соединение закрывается. Секрет мог меняться молча: #[cfg(not(unix))] fn write_secret_file(path: &Path, value: &str) { let _ = std::fs::write(path, value); // ошибка выброшена } create_dir_all рядом — так же. Если запись в %APPDATA%\TGLock\secret не удавалась, программа генерировала новый секрет при каждом запуске и ничего об этом не сообщала. Теперь write_secret_file возвращает Result, load_or_create_secret_at отдаёт StoredSecret с полем write_error, а оба интерфейса показывают предупреждение: CLI строкой при старте, GUI записью в журнал. Прокси при этом продолжает работать — просто до перезапуска. Тесты: every_route_failure_is_counted, a_failed_write_is_reported_instead_of _swallowed (родитель пути — файл, поэтому каталог не создать), a_successful_write_reports_no_error (секрет переживает второй запуск). В диагностике интерфейса добавлена подсказка: падения маршрутов больше нуля при работающем Telegram — норма, значит закреплённый адрес недоступен и подключение идёт через запасной. Co-authored-by: by-sonic <171230345+by-sonic@users.noreply.github.com>
This commit is contained in:
+38
-4
@@ -27,12 +27,23 @@ pub struct Stats {
|
||||
pub last_route: AtomicU8,
|
||||
transport: crate::transport::TransportEngine,
|
||||
secret: [u8; 16],
|
||||
/// Почему секрет не удалось сохранить, если не удалось.
|
||||
secret_write_error: Option<String>,
|
||||
shutdown: Mutex<Option<tokio::sync::watch::Sender<bool>>>,
|
||||
}
|
||||
|
||||
impl Stats {
|
||||
pub fn new() -> Arc<Self> {
|
||||
Self::with_secret(initial_secret())
|
||||
Self::with_stored_secret(initial_secret())
|
||||
}
|
||||
|
||||
/// Построить с секретом, про который известно, сохранился он на диск или нет.
|
||||
///
|
||||
/// Если не сохранился, при следующем запуске ссылка `tg://proxy` изменится и
|
||||
/// Telegram скажет «прокси настроен неверно и будет отключён». Раньше это
|
||||
/// происходило молча (by-sonic/tglock#37).
|
||||
pub fn with_stored_secret(stored: crate::mtproto::StoredSecret) -> Arc<Self> {
|
||||
Self::build(stored.value, stored.write_error)
|
||||
}
|
||||
|
||||
/// Build with an explicit proxy secret.
|
||||
@@ -40,6 +51,15 @@ impl Stats {
|
||||
/// A daemon must pin this: the secret is half of the `tg://proxy` link, so
|
||||
/// generating a fresh one on restart breaks every configured client.
|
||||
pub fn with_secret(secret: [u8; 16]) -> Arc<Self> {
|
||||
Self::build(secret, None)
|
||||
}
|
||||
|
||||
/// Сообщение о том, почему секрет не сохранён, если он не сохранён.
|
||||
pub fn secret_write_error(&self) -> Option<&str> {
|
||||
self.secret_write_error.as_deref()
|
||||
}
|
||||
|
||||
fn build(secret: [u8; 16], secret_write_error: Option<String>) -> Arc<Self> {
|
||||
Arc::new(Self {
|
||||
running: AtomicBool::new(false),
|
||||
active: AtomicU32::new(0),
|
||||
@@ -50,6 +70,7 @@ impl Stats {
|
||||
last_route: AtomicU8::new(0),
|
||||
transport: crate::transport::TransportEngine::new(),
|
||||
secret,
|
||||
secret_write_error,
|
||||
shutdown: Mutex::new(None),
|
||||
})
|
||||
}
|
||||
@@ -58,6 +79,16 @@ impl Stats {
|
||||
crate::mtproto::telegram_secret(&self.secret)
|
||||
}
|
||||
|
||||
/// Сколько отдельных маршрутов не ответило.
|
||||
///
|
||||
/// Отличается от `ws_failures`: тот растёт только когда упали все маршруты
|
||||
/// и соединение не состоялось. Этот показывает перебор, который прошёл
|
||||
/// незаметно — например, когда закреплённый адрес мёртв, а запасной
|
||||
/// работает (by-sonic/tglock#32).
|
||||
pub fn route_failures(&self) -> u32 {
|
||||
self.transport.route_failures()
|
||||
}
|
||||
|
||||
pub fn set_worker_domain(&self, domain: &str) {
|
||||
let domains = domain
|
||||
.split([',', ';', ' '])
|
||||
@@ -75,13 +106,16 @@ impl Stats {
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
fn initial_secret() -> [u8; 16] {
|
||||
fn initial_secret() -> crate::mtproto::StoredSecret {
|
||||
crate::mtproto::load_or_create_secret()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn initial_secret() -> [u8; 16] {
|
||||
crate::mtproto::generate_secret()
|
||||
fn initial_secret() -> crate::mtproto::StoredSecret {
|
||||
crate::mtproto::StoredSecret {
|
||||
value: crate::mtproto::generate_secret(),
|
||||
write_error: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Claim the local port.
|
||||
|
||||
Reference in New Issue
Block a user