Commit Graph

4 Commits

Author SHA1 Message Date
by-sonic a87e26c581 feat(android): приложение под Android и переход на rustls
Android грузит приложение как нативную библиотеку и входит через JNI-символ, а
не через main. Поэтому Tauri-приложение переехало из src/main.rs в src/gui.rs
внутри библиотеки, с #[cfg_attr(mobile, tauri::mobile_entry_point)], а main.rs
стал обёрткой. Модуль объявлен как #[cfg(feature = "gui")], так что свойство
«--no-default-features даёт ядро без Tauri и WebView» сохранилось — проверено
сборкой и 51 тестом headless-варианта.

Переход на rustls — вынужденный, но выгодный. native-tls на Linux и Android
тянет OpenSSL, а openssl-sys не кросскомпилируется под aarch64-linux-android:
сборка падала на нём. rustls на чистом Rust, корневые сертификаты webpki вшиты
в бинарь. Побочно: на Linux исчезла зависимость от системного libssl, а образу
Docker больше не нужен даже ca-certificates.

На этом переходе тест живой сети поймал баг, который прошёл бы в релиз: rustls
0.23 отказывается угадывать криптопровайдер и ПАНИКУЕТ на первом TLS-
рукопожатии. Компиляция чистая, все офлайновые тесты зелёные — они ходят через
локальный маршрут без TLS. То есть в сборку ушло бы приложение, не способное
подключиться ни к чему. Провайдер (ring, кросскомпилируется под Android)
устанавливается в ensure_crypto_provider, регрессию держит тест
a_crypto_provider_is_available_for_tls. Живой тест против шести боевых
дата-центров Telegram проходит.

Прочее:
- open::that заменён на tauri-plugin-opener: у крейта open нет реализации под
  Android, а плагин работает на обеих платформах.
- Библиотека переименована в tglock_lib: одинаковые имена lib и bin давали
  коллизию выходных файлов, которую cargo обещает сделать ошибкой.
- Программный рендер WebView не применяется на Android — там GPU есть всегда,
  и переопределение только замедлило бы интерфейс.
- .gitignore: строка /gen скрывала весь сгенерированный Android-проект. Теперь
  игнорируются только артефакты сборки, local.properties и keystore.

Foreground service. Прокси — поток в процессе приложения, и без сервиса система
выгрузит его через минуты после сворачивания. Сервис стартует из MainActivity,
а не по команде из ядра: JNI-мост между Rust и Kotlin осознанно не делался,
чтобы не добавлять слой, который нельзя проверить. Плата — уведомление висит,
пока открыто приложение, даже при выключенной защите.

НЕ ПРОВЕРЕНО: вся Android-часть в рантайме. Устройств не подключено,
эмулятора и системных образов в SDK нет. APK собирается, но приложение никто
ни разу не запускал: ни интерфейс, ни сервис, ни тип specialUse на Android 14+,
ни запрос разрешения на уведомления. Поэтому Android-артефакт сознательно НЕ
добавлен в release.yml — публиковать нечего, пока никто не запустил это на
живом устройстве.
2026-07-30 15:19:40 +03:00
Никита Sonic b06272437c fix(gui): просить программный рендер, чтобы окно создавалось без 3D (#28)
Интерфейс построен на системном WebView, а тот без 3D-ускорения окно не
создаёт. Отсюда весь класс жалоб: не стартует в виртуалке, не стартует с
дефолтным драйвером Microsoft, не стартует без монитора. Диагноз в #17 дал
@de4me: в VirtualBox приложение запускается только после включения галочки
«Включить ускорение 3D».

Перед стартом Tauri TGLock теперь сам запрашивает программный рендер:
- Windows: WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS с --disable-gpu
  и --disable-gpu-compositing;
- Linux: WEBKIT_DISABLE_COMPOSITING_MODE и WEBKIT_DISABLE_DMABUF_RENDERER;
- macOS: не требуется, WebKit сам уходит в программный рендер.

Для панели со статусом программный рендер не стоит ничего заметного, поэтому
он выбран значением по умолчанию, а не аварийным режимом. Уже заданные
оператором переменные не перезаписываются, TGLOCK_FORCE_GPU=1 отключает
механизм целиком.

Логика вынесена в чистую функцию software_rendering_vars и покрыта четырьмя
тестами: значение по умолчанию, отключение через TGLOCK_FORCE_GPU, уважение
чужой переменной и правильный набор ключей на каждой платформе.

Версия поднята до 2.0.0-beta.2 в Cargo.toml, package.json и tauri.conf.json:
нужен тег, чтобы в релиз попали и tglock-cli, и этот фикс.

README получил отдельный вопрос в FAQ про «окно не появляется»,
ARCHITECTURE_V2.md — обновлённый пункт в Current limitations.

Co-authored-by: by-sonic <171230345+by-sonic@users.noreply.github.com>
2026-07-30 13:40:04 +03:00
Никита Sonic 55653ed0bc feat(cli): headless tglock-cli, GUI behind a feature, deep test coverage (#25)
Реализует направление PR #15 поверх архитектуры 2.0. Сам PR смерджить нельзя:
он патчит src/bypass.rs, src/network.rs и src/ws_proxy.rs, которых больше нет,
и правит системный DNS — в 2.0 это не нужно, потому что адреса Telegram зашиты
в маршрутах, а SNI остаётся настоящим. Взято разделение GUI/CLI и произвольный
bind-адрес, отброшены DNS-менеджмент и проверка root: CLI не требует прав.

Closes #10, #17 — GUI не создаёт окно без 3D-ускорения, на машине без монитора
и в виртуалке. Причина в WebView под Tauri, поэтому лечится не программным
рендером, а бинарём, в котором WebView нет вовсе: при выключенной фиче gui
Tauri и фронтенд в сборку не попадают. Отдельная задача CI собирает и гоняет
CLI на голом ubuntu без Node.js и без libwebkit2gtk.

Структура:
- src/lib.rs — ядро (mtproto, proxy, transport, config), без Tauri
- src/main.rs — GUI, required-features = ["gui"]
- src/bin/cli.rs — headless-бинарь на clap
- build.rs вызывает tauri_build только при включённой фиче gui

Исправлено по пути:
- Определение протокола: SOCKS5 и MTProto различались по первому байту, но
  is_reserved_init не исключает 0x05, поэтому примерно одно соединение из 256
  уезжало в SOCKS5-ветку и умирало. Теперь неоднозначный первый байт решается
  по полному 64-байтному init и секрету.
- Ярлык маршрута в UI: код 2 подписывался как «Cloudflare Worker», хотя это
  запасной Telegram IP, а системный DNS и настоящий Worker оба показывались
  как «Автоматический маршрут». Метки переехали в transport::route_label,
  общий для обоих интерфейсов.
- Секрет прокси: под DynamicUser и ProtectHome домашней папки нет, secret_path
  возвращает None и секрет генерировался заново при каждом старте, ломая всем
  настроенным клиентам tg://-ссылку. Добавлен --secret-file.
- README обещал Rust 1.75+, тогда как Cargo.toml требует 1.88 и CI это
  проверяет. Это и есть первопричина #3.

Политика доступа: прямые не-Telegram соединения разрешены только на loopback,
на любом сетевом адресе нужен явный --allow-direct. Правило из ISSUE_AUDIT о
том, что LAN не должен становиться открытым SOCKS5, теперь выражено в типе
ListenConfig и покрыто тестами.

Тесты: 46 в библиотеке + 12 в CLI. Появился сквозной тест туннеля против
мок-релея, который реализует сторону Telegram по obfuscated2 — проверяется
не внутренняя консистентность, а что реле получает ровно тот открытый текст,
который отправил клиент, и обратно. Плюс расписание backoff, фолбэк при всех
маршрутах в cooldown, валидация Worker-доменов, отказы SOCKS5, устойчивость
секрета к перезапуску и корректная остановка по SIGTERM.

Документация: секция CLI в README с юнитом systemd и Dockerfile.

Co-authored-by: by-sonic <171230345+by-sonic@users.noreply.github.com>
2026-07-30 13:12:21 +03:00
Никита Митусов c25bea1d92 feat: rebuild TGLock with adaptive transport and Tauri UI 2026-07-29 15:22:54 +03:00