Files
rustdesk-custom/docs/CODEMAP.md
T
gusadmin dc15b03156 Custom-client: сервер виден+залочен + preset-пароль (Win+Android)
preconfigure.sh генерит src/custom_client.json (override-settings
server/relay/key + verification-method + disable-change-permanent-password;
preset-пароль salt+00b64(sha256(pw+salt)) в HARD_SETTINGS) и патчит
common.rs встроенным неподписанным загрузчиком (обход ED25519-подписи
RustDesk). Пароль из RUSTDESK_PRESET_PASSWORD, plaintext не хранится.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 18:23:56 +03:00

113 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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` | `[<tag>|latest]` → тянет пины тулчейна из CI-конфигов целевого тега RustDesk (flutter-build.yml + bridge.yml) и переписывает `upstream.txt` (с диффом). Так бамп версии не разъезжается с Flutter/vcpkg/LLVM/FRB/NDK. |
| `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/`. |
| `config/server.env.example` | Шаблон значений. Реальный `config/server.env` — в `.gitignore`. |
| `.gitea/workflows/` | CI: `build-windows.yaml` (раннер `windows:host`), `build-android.yaml` (VM 118). *(в работе)* |
| `rustdesk/` | Клон апстрима (gitignored, создаётся сборкой). |
| `dist/` | Готовые артефакты (gitignored). |
## Механизм преднастройки (важно)
RustDesk 1.4.9, `libs/hbb_common/src/config.rs` (сабмодуль `rustdesk/hbb_common`, пин `7e1c392`):
```rust
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 (поднять один раз на GUSIK-PC)
Версии — из `upstream.txt` (пины из `flutter-build.yml@1.4.9`):
- **Rust 1.75** — `rustup 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-заглушка (GUSIK-PC)
`build.py --flutter` в конце зовёт `python3 ./generate.py` для сборки портативного установщика. На
GUSIK-PC `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.py``target/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 toolchain (VM 118, позже)
Flutter 3.24.5, NDK r28c, cargo-ndk 3.1.2, Rust android-таргеты, vcpkg android-триплеты
(oboe, cpu-features, ffmpeg host=false). Публикация APK: gitea release + F-Droid (шаблон GusVoice).
## Грабли: прокси и vcpkg (GUSIK-PC)
На машине в env задан `NO_PROXY=...,192.168.5.0/24,...` (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).
## Тулчейн (фактические пути на GUSIK-PC)
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-method``KEYS_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 нигде.