RustDesk is a cross-platform remote desktop application written in Rust. It provides peer-to-peer remote desktop access with support for screen sharing, remote control, file transfer, audio streaming, and terminal access. The system operates with a multi-process architecture and supports connections through direct peer-to-peer (with NAT traversal) or via relay servers.
This page provides a high-level overview of the entire RustDesk codebase, its architecture, and how major components interact. For detailed information about specific subsystems:
RustDesk implements a complete remote desktop solution with the following capabilities:
| Capability | Description |
|---|---|
| Remote Desktop Control | Full keyboard/mouse control of remote systems with video streaming |
| File Transfer | Bidirectional file transfer with resume support |
| Port Forwarding | TCP tunneling for accessing remote services |
| Audio Streaming | Voice calls and remote audio playback |
| Terminal Access | Remote shell access with PTY support |
| Camera Viewing | Remote camera access |
| NAT Traversal | UDP/TCP hole punching for direct peer-to-peer connections |
The codebase is structured to support multiple UI frameworks (Flutter primary, Sciter deprecated), multiple operating systems (Windows, Linux, macOS, Android, iOS), and various hardware codec implementations.
Sources: README.md20-28 src/server/connection.rs1-305 src/client.rs1-100
Sources: README.md159-171 src/flutter_ffi.rs1-100 src/client.rs184-230 src/server/connection.rs349-489
RustDesk uses separate processes for privilege separation and stability:
Process Responsibilities:
| Process | Flag | Primary Role | Key Files |
|---|---|---|---|
| Main | --default | UI, user input, client connections | src/main.rs flutter/ |
| Server | --server | Accept incoming connections, manage sessions | src/server/connection.rs350-489 |
| CM | --cm | Connection manager UI, file operations | src/flutter.rs src/ui_cm_interface.rs |
The server process spawns a Connection instance for each incoming remote client. Each Connection manages its own service subscriptions (video, audio, input, clipboard).
Sources: src/server/connection.rs207-305 src/ipc.rs src/main.rs
RustDesk establishes connections through a multi-step process involving NAT traversal:
Key Classes in Connection Flow:
Client::start() in src/client.rs188-230 - Initiates outbound connectionsClient::_start_inner() in src/client.rs366-627 - NAT traversal and relay logicConnection::start() in src/server/connection.rs350-489 - Handles incoming connectionsConnInner in src/server/connection.rs126-130 - Represents connection endpoint for servicesSubscriber trait for service pub-sub patternSources: src/client.rs188-627 src/server/connection.rs126-489 src/rendezvous_mediator.rs
Services implement a publish-subscribe pattern where connections subscribe to needed services:
Service Names (Constants):
video_service::NAME - Video frame streaminginput_service::NAME - Input event processingaudio_service::NAME - Audio streamingclipboard_service::NAME - Text clipboard syncclipboard_service::FILE_NAME - File clipboard (Windows/Linux)NAME_CURSOR - Cursor position updatesNAME_POS - Window position updatesSources: src/server/connection.rs593-663 src/server/video_service.rs src/server/input_service.rs
The Flutter UI communicates with the Rust core through FFI:
Key FFI Functions:
session_start() in src/flutter_ffi.rs178-184 - Start a sessionsession_send_mouse() - Send mouse eventssession_input_key() in src/flutter_ffi.rs628-642 - Send keyboard inputsession_login() in src/flutter_ffi.rs232-242 - Authenticate connectionmain_get_option() / main_set_option() in src/flutter_ffi.rs945-1017 - ConfigurationThe FlutterHandler implements InvokeUiSession trait to push events back to Flutter via StreamSink<EventToUI>.
Sources: src/flutter_ffi.rs1-200 src/flutter.rs200-450 src/ui_session_interface.rs1-100
Video frames flow from screen capture through encoding to the client UI:
Key Components:
video_service::run() spawns per-display capture threadsCapturer implementations in libs/scrap/src/ for each platformEncoder in libs/scrap/src/common/codec.rsVideoFrameController in src/server/video_service.rs manages frame pacingDecoder::handle_video_frame() in client processes framesFlutterHandler::on_rgba() or texture rendering pushes to UISources: src/server/video_service.rs libs/scrap/src/common/codec.rs src/client/io_loop.rs src/flutter.rs240-450
Communication uses Protocol Buffers defined in hbb_common::message_proto:
| Message Type | Purpose | Key Fields |
|---|---|---|
LoginRequest | Initial authentication | username, password, my_id, option |
LoginResponse | Auth result | error, peer_info |
VideoFrame | Video data | vp8s/vp9s/av1s/h264s/h265s union |
CursorPosition | Cursor location | x, y |
CursorData | Cursor image | id, hotx, hoty, width, height, colors |
MouseEvent | Mouse input | mask, x, y, modifiers |
KeyEvent | Keyboard input | chr, down, press, mode, modifiers |
Clipboard | Clipboard sync | compress, content or cliprdr |
FileAction | File operations | send/receive/remove_file/all_files union |
Misc | Control messages | audio_format/chat_message/switch_display union |
Messages are sent via Stream::send(&Message) and received via Stream::next().
Sources: hbb_common/protos/message.proto src/server/connection.rs768-1500 src/client/io_loop.rs225-355
RustDesk uses a multi-layered configuration system:
Configuration Storage:
LocalConfig stored in {APP_DIR}/config/RustDesk.toml (hbb_common/src/config.rs)PeerConfig stored in {APP_DIR}/config/peers/{peer_id}.tomlSources: hbb_common/src/config.rs src/client.rs44-73 src/ui_session_interface.rs199-650
RustDesk implements a sophisticated remote desktop system with:
The architecture prioritizes performance (hardware encoding, efficient IPC), security (process isolation, encryption), and portability (platform abstraction, multiple UI frameworks).
For deeper understanding of specific subsystems, refer to the linked sections at the top of this page.
Sources: README.md1-183 src/server/connection.rs1-305 src/client.rs1-230 src/flutter_ffi.rs1-200
Refresh this wiki
This wiki was recently refreshed. Please wait 1 day to refresh again.