CodeVetter · Repo Unpack · Extension points
rustdesk/rustdesk
Extension happens at five seams: (1) the Service registry — implement `Service`/`Subscriber` and register in `server::new()`; (2) ConnType — add a variant through protos + session_add dispatch + Flutter WindowType; (3) option keys — append to libs/base/src/config/keys.rs and src/lang template; (4) CLI flags — extend the args[0] chain in core_main; (5) Flutter FFI — new pub fns in flutter_ffi.rs + flutter_rust_bridge codegen. Platform code goes in src/platform/*, not shared paths.
- Service plugin point: implement `trait Service` (or reuse ServiceTmpl<T: Subscriber>) and call `server.add_service(Box::new(...))` in `new()` — video services are even added dynamically at runtime via try_add_monitor_service/try_add_primary_camera_service keyed by `get_service_name(VideoSource, idx)`.
- New connection type: add a ConnType in message proto (hbb_common/base protos), branch it in `session_add` (is_* bools), map it in `peer_get_sessions_count`, add a WindowType + kAppType in Flutter main.dart, and handle the login_request::Union arm in connection.rs.
- Option keys: single import path `base::config::keys` re-exports hbb_common's keys plus ~100 client keys; new options are added as `pub const OPTION_*` and consumed via config::option2bool/Config::get_option — server-pushed strategies can set them remotely.
- CLI extension is a linear `else if args[0] == "--x"` chain in core_main; note the pattern of gating management commands behind `platform::is_installed() && is_root()` and routing root CLI to user IPC via UserMainIpcScope/is_user_main_ipc_scope_cli_command.
- IPC message extension: add variants to serde-tagged `enum Data` (and FS/DataKeyboard/etc. sub-enums); both ipc::start listener handlers and ui_cm_interface consumers must be updated; FileBlockFromCM documents the raw-bytes side-channel protocol (send message then send_raw).
- Flutter FFI extension: add `pub fn` in src/flutter_ffi.rs (naming convention: session_*, main_*, peer_*; SyncReturn for sync calls) and regenerate bridge_generated via flutter_rust_bridge 1.80; events to UI go through GLOBAL_EVENT_STREAM via push_global_event(channel, json).
- Localization: add keys to src/lang/template.rs + every locale file per AGENTS.md rules (en.rs only when display differs from key; it.rs always empty string); keys are the English text themselves, sentence-case.
- Platform seams: src/platform/{windows.rs,linux.rs,macos.rs} + per-OS subdirs implement the hooks called from shared code (install_me, is_installed, elevate_or_run_as_system, check_autostart_config...); AGENTS.md mandates putting new platform logic in these modules with thin call-site hooks.
- Codec/capture backends are cfg-gated extensions in libs/scrap (dxgi, quartz, x11, wayland, android, drm capturer) and codec EncoderCfg dispatch in video_service — adding a capture backend means a new scrap module + feature flag + service wiring.
- Privacy-mode impls are pluggable per-OS under src/privacy_mode/ (win_mag, win_virtual_display, win_exclude_from_capture, win_topmost_window, macos) selected via is_current_privacy_mode_impl/PRIVACY_MODE_IMPL_* constants.
- Custom-server branding is a deployment-time extension: embed signed CustomServer JSON (host/key/api/relay) via exe filename or config string — verified against a hardcoded sign::PublicKey — rather than a plugin API.
- AGENTS.md's own extension doctrine: prefer purely additive #[cfg]-gated blocks and new functions over restructuring; 'feature off must run the old code'; shared-file changes should be thin one-line hooks — this is the enforced contribution contract.