From b4c629239700eab689db98fa94feff17ff9496bb Mon Sep 17 00:00:00 2001 From: ClSlaid Date: Sun, 5 Nov 2023 18:11:05 +0800 Subject: [PATCH] docs: file copy paste explainations Signed-off-by: ClSlaid --- README.md | 6 +- libs/clipboard/README.md | 145 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 924cd1786..a805c2ca8 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Chat with us: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk) -[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09) +[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09) [![Open Bounties](https://img.shields.io/endpoint?url=https%3A%2F%2Fconsole.algora.io%2Fapi%2Fshields%2Frustdesk%2Fbounties%3Fstatus%3Dopen)](https://console.algora.io/org/rustdesk/bounties?status=open) @@ -80,11 +80,12 @@ sudo apt install -y zip g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxc libclang-dev ninja-build libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev ``` -### openSUSE Tumbleweed +### openSUSE Tumbleweed ```sh sudo zypper install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libXfixes-devel cmake alsa-lib-devel gstreamer-devel gstreamer-plugins-base-devel xdotool-devel ``` + ### Fedora 28 (CentOS 8) ```sh @@ -170,6 +171,7 @@ Please ensure that you are running these commands from the root of the RustDesk - **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: video codec, config, tcp/udp wrapper, protobuf, fs functions for file transfer, and some other utility functions - **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: screen capture - **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: platform specific keyboard/mouse control +- **[libs/clipboard](https://github.com/rustdesk/rustdesk/tree/master/libs/clipboard)**: file copy and paste implemention for Windows, Linux, OSX. - **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: obsolete Sciter UI (deprecated) - **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: audio/clipboard/input/video services, and network connections - **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: start a peer connection diff --git a/libs/clipboard/README.md b/libs/clipboard/README.md index ea2b85785..6333a0644 100644 --- a/libs/clipboard/README.md +++ b/libs/clipboard/README.md @@ -3,8 +3,74 @@ Copy files and text through network. Main lowlevel logic from [FreeRDP](https://github.com/FreeRDP/FreeRDP). +To enjoy file copy and paste feature on Linux/OSX, +please build with `unix-file-copy-paste` feature. + TODO: Move this lib to a separate project. +## How it works + +Terminalogies: + +- cliprdr: this module +- local: the endpoint which initiates a file copy events +- remote: the endpoint which paste the file copied from `local` + +The main algorithm of copying and pasting files is from +[Remote Desktop Protocol: Clipboard Virtual Channel Extension](https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-RDPECLIP/%5bMS-RDPECLIP%5d.pdf), +and could be concluded as: + +0. local and remote notify each other that it's ready. +1. local subscribes/listening to the system's clipboard for file copy +2. local once got file copy event, notice the remote +3. remote confirms receive and try pulls the file list +4. local updates its file-list, the remote flushes pulled file list to the clipboard +5. remote OS or desktop manager initiates a paste, making other programs reading + clipboard files. Convert those reading requests to RPCs + + - on Windows, all file reading will go through the stream file API + - on Linux/OSX, FUSE is used for converting reading requests to RPCs + - in case of local clipboard been transferred back + and leading to a dead loop, + all file copy event pointing at the FUSE directory will be ignored + +6. finishing pasting all files one by one. + +In a perspective of network data transferring: + +```mermaid +sequenceDiagram + participant l as Local + participant r as Remote + note over l, r: Initialize + l ->> r: Monitor Ready + r ->> l: Monitor Ready + loop Get clipboard update + l ->> r: Format List (I got update) + r ->> l: Format List Response (notified) + r ->> l: Format Data Request (requests file list) + activate l + note left of l: Retrive file list from system clipboard + l ->> r: Format Data Response (containing file list) + deactivate l + note over r: Update system clipboard with received file list + end + loop Some application requests copied files + note right of r: application reads file from x to x+y + note over r: the file is the a-th file on list + r ->> l: File Contents Request (read file a offset x size y) + activate l + note left of l: Find a-th file on list, read from x to x+y + l ->> r: File Contents Response (contents of file a offset x size y) + deactivate l + end +``` + +Note: In actual implementation, both sides could play send clipboard update +and request file contents. +There is no such limitation that only local can update clipboard +and copy files to remote. + ## impl ### windows @@ -14,3 +80,82 @@ TODO: Move this lib to a separate project. ![A1->B1](./docs/assets/win_A_B.png) ![B1->A1](./docs/assets/win_B_A.png) + +The protocol was originally designed as an extension of the Windows RDP, +so the specific message packages fits windows well. + +When starting cliprdr, a thread is spawn to create a invisible window +and to subscribe to OLE clipboard events. +The window's callback (see `cliprdr_proc` in `src/windows/wf_cliprdr.c`) was +set to handle a variaty of events. + +Detailed implementation is shown in pictures above. + +### Linux/OSX + +The Cliprdr Server implementation has mainly 3 parts: + +- Clipboard Client +- Local File list +- FUSE server + +#### Clipboard Client + +The clipboard client has a thread polling for file urls on clipboard. + +If the client found any updates of file urls, +after filtering out those pointing to our FUSE directory or duplicated, +send format list directly to remote. + +The cliprdr server also uses clipboard client for setting clipboard, +or retrive paths from system. + +#### Local File List + +The local file list is a temperary list of file metadata. +When receiving file contents PDU from peer, the server picks +out the file requested and open it for reading if necessary. + +Also when receiving Format Data Request PDU from remote asking for file list, +the local file list should be rebuilt from file list retrieved from Clipboard Client. + +Some caching and preloading could done on it since applications are likely to read +on the list sequentially. + +#### FUSE server + +The FUSE server could convert POSIX file reading request to File Contents +Request/Response RPCs. + +When received file list from remote, +the FUSE server will figure out the file system tree and rearrange its content. + +#### Groceries + +- The protocol was originally implemented for windows, + so paths in PDU will all be converted to DOS formats in UTF-16 LE encoding, + and datetimes will be converted to LDAP timestamp instead of + unix timestamp + + ```text + UNIX + /usr/bin/rustdesk + -> + DOS + \usr\bin\rustdesk + ``` + +- To better fit for preserving permissions on unix-like platforms, + a reserved area of FileDescriptor PDU + +- you may notice + the mountpoint is still occupied after the application quits. + That's because the FUSE server was not mounted with `AUTO_UNMOUNT`. + - It's hard to implement gressful shutdown for a multi-processed program + - `AUTO_UNMOUNT` was not enabled by default and requires enable + `user_allow_other` in configure. Letting users edit such global + configuration to use this feature might not be a good idea. + - use [`umount()`](https://man7.org/linux/man-pages/man2/umount.2.html) + syscall to unmount will also require that option. + - we currently directly call [`umount`](https://man7.org/linux/man-pages/man8/umount.8.html) + program to unmount dangling FUSE server. It worked perfectly for now.