Files
rustdesk-custom/docs/CODEMAP.md
T
gusadmin 1b3c3496c5 Приватность публичного репо + выкл. проверку обновлений + релиз latest
- Убраны все машинно/инфра-специфичные данные из README/CODEMAP/скриптов/
  workflows (хосты, IP, домен gitea -> github.server_url).
- preconfigure: enable-check-update=N (выкл. проверку обновлений); подсказка
  «set up your own server» и так гаснет с override-сервером.
- CI публикует exe/apk в Gitea Release `latest` (обновляется каждый прогон,
  стабильная ссылка) + версионный релиз на теге v*.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 19:13:54 +03:00

13 KiB
Raw Blame History

CODEMAP — rustdesk-custom

Карта overlay-репозитория для преднастроенной сборки RustDesk. Держать актуальной при каждом изменении.

Структура

Путь Назначение
upstream.txt Пины: RUSTDESK_TAG, версии Rust/LLVM/Flutter, VCPKG_COMMIT_ID, VCPKG_TRIPLET, Android-пины. Единственный источник версий.
scripts/preconfigure.sh Патчит RENDEZVOUS_SERVERS и RS_PUB_KEY в hbb_common/src/config.rs клона. Значения из env. Проверяет, что патч применился.
scripts/bump-upstream.sh `[
scripts/provision-windows.ps1 Идемпотентно доводит тулчейн до пинов (Rust+rustfmt, Flutter, LLVM, vcpkg@коммит). Ставит только отсутствующее/несовпадающее. Зовётся из build-windows.ps1 (skip: RD_SKIP_PROVISION=1).
scripts/build-windows.ps1 Оркестратор Windows-сборки: provision → load env → клон@пин → preconfigure → codegen → vcpkg install → build.py → портативный установщик → dist/.
scripts/provision-android.sh Идемпотентный Android-тулчейн на build-VM под пины (Flutter/NDK/cargo-ndk/vcpkg/JDK17/apt). Пишет ~/dev/rd-android.env.
scripts/build-android.sh Оркестратор Android APK (arm64-v8a): env → клон@пин → preconfigure → build_android_deps → codegen → cargo-ndk → jniLibs → flutter apk → dist/.
config/server.env.example Шаблон значений. Реальный config/server.env — в .gitignore.
.gitea/workflows/ CI: build-windows.yaml (раннер windows, зелёный), build-android.yaml (раннер android/build-VM).
rustdesk/ Клон апстрима (gitignored, создаётся сборкой).
dist/ Готовые артефакты (gitignored).

Механизм преднастройки (важно)

RustDesk 1.4.9, libs/hbb_common/src/config.rs (сабмодуль rustdesk/hbb_common, пин 7e1c392):

pub const RENDEZVOUS_SERVERS: &[&str] = &["rs-ny.rustdesk.com"];
pub const RS_PUB_KEY: &str = "OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=";
  • option_env!(RENDEZVOUS_SERVER/RS_PUB_KEY) из старого PR #2810 в master вырезан — только патч констант.
  • Порт hbbs по умолчанию 21116 (не указывать, если стандартный). Нестандартный — host:port.
  • API-сервер (только RustDesk Server Pro) отдельной const в 1.4.9 не имеет; для обычного hbbs/hbbr не нужен.
  • Альтернатива без сборки (на будущее): переименовать официальный бинарь в rustdesk-host=<server>,key=<pubkey>.exe — конфиг читается из имени файла (EXE_RENDEZVOUS_SERVER).

Windows toolchain (поднять один раз на Windows-хосте)

Версии — из upstream.txt (пины из flutter-build.yml@1.4.9):

  • Rust 1.75rustup toolchain install 1.75; в дереве клона rustup override set 1.75 (апстрим держит 1.75 из-за i128 ABI-изменения в 1.78+).
  • LLVM 15.0.6 — для bindgen; задать LIBCLANG_PATH на bin LLVM.
  • Flutter 3.24.5 (канал stable) в PATH. Апстрим применяет патч .github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff к SDK — при ошибке сборки применить.
  • vcpkg@120deac3 — склонировать, bootstrap-vcpkg, задать VCPKG_ROOT. Триплет x64-windows-static. Зависимости из vcpkg.json: aom, libvpx, libyuv, opus, libjpeg-turbo, mfx-dispatch, ffmpeg (static, features amf/nvcodec/qsv — hwcodec). ffmpeg/aom — длинная первая компиляция.
  • Сборка: python build.py --flutter (флаги: --hwcodec, --portable, --vram, --skip-cargo).

Грабля: bridge_generated.rs (обязательный codegen)

RustDesk не коммитит src/bridge_generated.rs (lib.rs объявляет mod bridge_generated;). Без генерации cargo build падает: E0583 file not found for module bridge_generated + E0277 EventToUI: IntoIntoDart. Генерится flutter_rust_bridge_codegen (в CI RustDesk — отдельный bridge.yml):

cargo +stable install cargo-expand --version 1.0.95 --locked
cargo +stable install flutter_rust_bridge_codegen --version 1.80.1 --features uuid --locked
pushd flutter && flutter pub get && popd
RUSTC_BOOTSTRAP=1 flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs \
  --dart-output ./flutter/lib/generated_bridge.dart --c-output ./flutter/macos/Runner/bridge_generated.h \
  --llvm-path S:/dev/LLVM   # ffigen ищет libclang.dll в дефолтных путях, LLVM у нас на S:

Пины FRB_VERSION/CARGO_EXPAND_VERSION — в upstream.txt. Шаг встроен в build-windows.ps1 перед build.py. RUSTC_BOOTSTRAP=1 нужен, т.к. cargo-expand требует nightly-фич, а тулчейн 1.75 stable. Грабля: codegen зовёт rustfmt; без него (rustup component add rustfmt --toolchain 1.75-...) он крэшится ПОСЛЕ генерации rust-моста, но ДО dart-стороны — bridge_generated.rs есть, а generated_bridge.dart/.freezed.dart нет → flutter build падает EventToUI_Event/RustdeskImpl isn't a type. Поэтому проверять надо dart-файлы, не только rust.

Грабля: portable-pack и python3-заглушка (Windows-хосте)

build.py --flutter в конце зовёт python3 ./generate.py для сборки портативного установщика. На Windows-хосте python3 = Microsoft Store-заглушка (реальный только python = 3.12) → шаг падает («Python Error occurred when executing generate.py»), хотя клиент к этому моменту уже собран в flutter/build/windows/x64/runner/Release/. Поэтому build-windows.ps1 зовёт build.py --skip-portable-pack, а установщик пакует отдельным шагом реальным python generate.pytarget/release/rustdesk-portable-packer.exe → копия в dist/rustdesk-<tag>-install.exe.

Разрешённый вопрос: flutter-engine

Стоковый Flutter 3.24.5 x64 engine отработал — flutter build windows собрался БЕЗ кастомного windows-x64-release.zip (тот нужен апстриму только для Win7). Для Win10/11 подмена не требуется.

Android (build-VM, раннер android)

Тулчейн: scripts/provision-android.sh (Flutter 3.24.5, NDK r28c от Google напрямую, cargo-ndk 3.1.2, Rust+aarch64-target, vcpkg@пин, FRB codegen; apt: clang/cmake/nasm/libssl-dev/openjdk-17). Пишет ~/dev/rd-android.env. Ставит в ~/dev (нужно ~40 ГБ свободного места под vcpkg-android/target). Сборка: scripts/build-android.sh (arm64-v8a): клон@пин → preconfigure → build_android_deps.sh arm64-v8a (vcpkg под arm, ffmpeg/aom из исходников — долго) → FRB codegen (--llvm-path авто) → cargo ndk build → jniLibs (.so+libc++_shared.so) → flutter build apkdist/rustdesk-<tag>-arm64.apk. Пороговый Rust-target ставит provision. Пин submodule hbb_common, пины из upstream.txt.

Android-грабли (все зашиты в скрипты)

  • openssl-sys (host): cargo ndk падал «Could not find OpenSSL» для host-таргета → libssl-dev (provision).
  • bindgen NDK-sysroot: magnum-opus/hwcodec/scrap bindgen резолвил #include <stdint.h> в host-glibc → bits/libc-header-start.h not found. Фикс: BINDGEN_EXTRA_CLANG_ARGS_aarch64_linux_android="--sysroot=$NDK/.../sysroot --target=aarch64-linux-android21" (build-android.sh).
  • hwcodec: пока БЕЗ него (RUSTDESK_ANDROID_FEATURES=flutter); его build.rs добавлял свои bindgen-грабли. Включить: RUSTDESK_ANDROID_FEATURES=flutter,hwcodec (после доводки).
  • Java/Gradle: VM дефолт Java 21, Gradle 7.6.4 не тянет → JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 (build-android.sh, как RustDesk CI). Kotlin e:-варнинги (metadata 2.1.0 vs 1.6.0) — НЕ фатальны.
  • Подпись: release требует key.properties → без него патчим build.gradle на debug-подпись (signingConfig = key.properties есть ? release : debug). Свой keystore = flutter/android/key.properties.

Публикация APK: .gitea/workflows/build-android.yaml (раннер android) → gitea release на теге. F-Droid — позже.

Грабли: прокси и vcpkg (Windows-хосте)

На машине в env задан NO_PROXY=...,10.0.0.0/8,... (CIDR). WinHTTP-загрузчик vcpkg (и bootstrap.ps1) не парсит CIDR → падает с WinHttpSetOption/WinHttpOpen error 87/0x57 на первом же скачивании (nasm и т.п.). У машины есть прямой интернет (netsh winhttp = Direct, HEAD к nasm.us = 200), поэтому build-windows.ps1 очищает HTTP(S)_PROXY/NO_PROXY для процесса сборки — качается напрямую. vcpkg.exe тоже качали вручную через IWR (bootstrap не смог) — лежит в S:\dev\vcpkg\vcpkg.exe (tool 2025-07-21).

Тулчейн (фактические пути на Windows-хосте)

Flutter: S:\dev\flutter · vcpkg: S:\dev\vcpkg (VCPKG_ROOT) · LLVM 15.0.6: S:\dev\LLVM (VS-бандл содержит только clang-format/tidy, БЕЗ libclang.dll — ставили LLVM отдельно, LIBCLANG_PATH=S:\dev\LLVM\bin) · Rust 1.75 (rustup override в клоне) · MSVC 14.44 из vcvars64.

Секреты в CI (gitea Actions)

RUSTDESK_SERVER, RUSTDESK_PUB_KEY, (опц.) RUSTDESK_API_SERVER. Префикс имён — не GITHUB_/GITEA_ (зарезервированы), при необходимости GT_.

Custom-client: сервер виден+залочен + preset-пароль

Требование: сервер показан в Настройках и НЕизменяем + вшитый постоянный пароль (+ временный). Механизм RustDesk (изучен по коду 1.4.9):

  • src/common.rs::load_custom_client() (зовётся из core_main) читает custom.txt рядом с exe — base64 + ED25519-подпись по вшитому pubkey 5Qbwsde3… (приватник у генератора RustDesk Pro, у нас нет).
  • Он заполняет OVERWRITE_SETTINGS (override — залоченные опции), DEFAULT_SETTINGS, BUILTIN_SETTINGS (локи), HARD_SETTINGS (top-level, вкл. preset-пароль).
  • custom-rendezvous-server/relay-server/key/api-server/verification-methodKEYS_SETTINGS → в override-settings показываются И залочены. disable-change-permanent-password ∈ BUILDIN.
  • Preset-пароль (hbb_common/src/config/permanent_password.rs): HARD_SETTINGS.password="00"+base64(sha256(pw+salt)), HARD_SETTINGS.salt=<любая непустая соль>. Формат «00»+b64(h1), h1=sha256(pw+salt)[..32].

Наша реализация (preconfigure.sh, вкл. по умолчанию; выкл. RUSTDESK_NO_CUSTOM_CLIENT=1):

  • Пишет src/custom_client.json (override-settings + password/salt из RUSTDESK_PRESET_PASSWORD).
  • Патчит common.rs: добавляет read_custom_client_unsigned() (парсит JSON БЕЗ подписи, тот же apply-код) + include_str!("custom_client.json") в начало load_custom_client(). Работает Windows+Android (без внешнего файла).
  • Пароль — только из env/secret RUSTDESK_PRESET_PASSWORD, солёный хэш пишется в gitignored-клон, plaintext нигде.