* fix(tunnel): медиа и «прокси не настроен»: один пакет на кадр, настоящие фронты, kwsN-1 только для медиа
Три причины, каждая проверена на живом Telegram запросом req_DH_params:
сервер сверяет номер DC внутри него с собой и отвечает -444 на чужой.
- WebSocket-фронт разбирает один пакет на входящий кадр, остаток ждёт
следующего. Клиент пишет запросы пачками, TGLock слал их одним кадром,
и всё, что шло вторым, застревало: текст проходил, файлы вставали.
Теперь поток режется на пакеты, как в Flowseal/tg-ws-proxy. Пачка через
beta.18 висит на всех DC, через эту сборку принимается на всех.
- Кластер kwsN-1 отвергает обычное соединение с -444, а Telegram Desktop
в ответ выключает прокси как настроенный неверно. При сбое kwsN основное
соединение откатывалось именно туда. Теперь kwsN-1 только для медиа.
- Адреса из списка DC не говорят на TLS ни из какой сети (проверено с чистой
сети), поэтому первый маршрут каждого DC не работал никогда. Закреплены
настоящие фронты, и DC1, DC3, DC5 стали доступны по WebSocket, чего не было.
У CDN203 своего фронта нет: остались TCP, Worker и CF-прокси.
Обрыв туннеля, через который уже шли данные, больше не ставит маршрут на
паузу. Таймаут соединения 8 с, как в tg-ws-proxy. probe_proxy.mjs получил
--identity и --batched: они и нашли эти баги.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat: журнал ошибок в диагностике, --log-file для роутеров; 2.0.0-beta.19
«Скопировать диагностику» отдавала только счётчики, и по ней нельзя было
понять, какой маршрут не ответил. Теперь в отчёте есть строки сбоев туннелей,
а домены Worker и CF-прокси в них заменены на <домен>.
--log-file и --log-max-mb (log_file, log_max_mb в настройках), как в
tg-ws-proxy: журнал идёт в файл с ротацией, а не в системный журнал роутера.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(routes): запасной WebSocket на порту 80 родных адресов, включая CDN203
Родные адреса Telegram принимают WebSocket без TLS на порту 80. Измерено
req_DH_params: DC определяется адресом, имя хоста не важно, а 91.105.192.100
отдаёт ключи CDN. Для CDN203, откуда часто идёт видео, это первый прямой
WebSocket: на 443 фронта у него нет, и там, где провайдер закрыл только 443,
до него раньше было не достать без Worker.
Защита та же, что у родного TCP: внутри тот же обфусцированный MTProto. В Host
идёт адрес, имени Telegram в открытом виде нет. Маршрут разрешён только до
закреплённых адресов и пробуется последним.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(routes): паузы маршрутов по результатам ревью, пределы и журнал
- Обрыв не наказывает маршрут, только если туннель работал и получал ответы
15 с. Одного ответа мало: маршрут, который ответил раз и умер, оставался
предпочтительным навсегда.
- Клиент спросил, не дождался ответа за 5 с и ушёл: маршрут считается
неработающим. Иначе CDN, принявший TCP и молчащий, держал первое место, и
очередь до порта 80 не доходила.
- Предел пакета 2 МиБ вместо 16: чужое устройство в LAN-режиме не заставит
роутер копить десятки мегабайт на соединение.
- Журнал: разовая ошибка записи его больше не выключает, неудачная ротация
не теряет бэкап и держит предел, права 0600 и на уже существующем файле.
- В отчёт диагностики не попадает Worker, заданный адресом.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: babin <Thartewerner536e@engineer.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Evidence from runs 39866280662, 39870244857 and 40091145294 shows the red
smoke runs were the emulator, not TGLock: on the software GPU the WebView
paints about one frame per second while the page re-renders every second,
so a tap's down/up can straddle a re-render and Chromium drops the click
(no setEnabled call at all in the failed Stop run). Play services and Pixel
Launcher post-boot work also starved system_server into foreign ANR dialogs.
- AOSP image, 4 cores, 4 GB RAM, no snapshot save; wait for CPU to settle
after boot before launching.
- Answer foreign "isn't responding" dialogs with Wait and record them; a
TGLock ANR/error dialog, crash or missing process still fails.
- Re-tap only when the button is unchanged 10s after a tap (at most 3 taps);
foreground-service and SOCKS listener effects stay strictly asserted with
a 45s budget sized for this emulator.
- Timed step markers in stdout and logcat, failure screenshot and window
dump, one evidence artifact per run attempt.
Co-authored-by: babin <Thartewerner536e@engineer.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
On the loaded API 35 emulator `uiautomator dump` intermittently writes no
file ("could not get idle state"). tap_label passed that straight to
`cat` and failed the whole smoke on the first miss, while the launch loop
already retried. The beta.16 commit failed four runs in a row this way;
the identical tree passed on its PR. Only the dump is retried — crash,
ANR, service and listener assertions are unchanged.
Co-authored-by: babin <Thartewerner536e@engineer.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix: address routing, media, worker and platform issues
* ci: use available Android tools and verify Windows CLI artifact
* fix(gui): return a result from asynchronous stop command
* test(android): verify installed APK and proxy lifecycle on emulator
* fix(media): use native MTProto for CDN203 and retain recent diagnostics
* Fix owned WebSocket split after transport boxing
* Clarify CDN transport and connection status guarantees
* Recognize accessible Android power button labels
* chore(release): prepare 2.0.0-beta.15 with verified draft publication
---------
Co-authored-by: babin <Thartewerner536e@engineer.com>
Проверка содержимого бандла, добавленная в #33, работала на Linux и давала
ложное «в бандле не GUI» на macOS. Причина в BSD grep: в UTF-8-локали он молча
не находит строки в бинарных данных там, где GNU grep находит. Из-за этого
задача macOS в релизе beta.4 упала уже после загрузки артефактов, а вместе с
ней снова пропустилась задача с CLI-бинарями.
Сами артефакты beta.4 при этом корректны — проверено скачиванием: в бандле
tglock на 20.3 МБ, universal/fat, признаки GUI на месте, признаков CLI нет.
Не хватает только tglock-cli-*.
Проверка вынесена в scripts/verify_bundle_binary.py и вызывается из всех трёх
мест: задачи CI bundle, проверки macOS и проверки Linux в релизе. Один скрипт
вместо трёх копий шелл-кода исключает и платформенные различия grep, и
расхождение копий между собой.
Скрипт проверен на реальных исторических артефактах:
beta.4 (исправный) → код 0
beta.3 (сломанный) → код 1, найдены allow-direct и secret-file
beta.2 (сломанный) → код 1, то же