Merge branch 'rustdesk:master' into master
This commit is contained in:
commit
70a4ee4318
181
.github/workflows/ci.yml
vendored
Normal file
181
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,181 @@
|
||||
name: CI
|
||||
|
||||
# env:
|
||||
# MIN_SUPPORTED_RUST_VERSION: "1.46.0"
|
||||
# CICD_INTERMEDIATES_DIR: "_cicd-intermediates"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
# ensure_cargo_fmt:
|
||||
# name: Ensure 'cargo fmt' has been run
|
||||
# runs-on: ubuntu-20.04
|
||||
# steps:
|
||||
# - uses: actions-rs/toolchain@v1
|
||||
# with:
|
||||
# toolchain: stable
|
||||
# default: true
|
||||
# profile: minimal
|
||||
# components: rustfmt
|
||||
# - uses: actions/checkout@v2
|
||||
# - run: cargo fmt -- --check
|
||||
|
||||
# min_version:
|
||||
# name: Minimum supported rust version
|
||||
# runs-on: ubuntu-20.04
|
||||
# steps:
|
||||
# - name: Checkout source code
|
||||
# uses: actions/checkout@v2
|
||||
|
||||
# - name: Install rust toolchain (v${{ env.MIN_SUPPORTED_RUST_VERSION }})
|
||||
# uses: actions-rs/toolchain@v1
|
||||
# with:
|
||||
# toolchain: ${{ env.MIN_SUPPORTED_RUST_VERSION }}
|
||||
# default: true
|
||||
# profile: minimal # minimal component installation (ie, no documentation)
|
||||
# components: clippy
|
||||
# - name: Run clippy (on minimum supported rust version to prevent warnings we can't fix)
|
||||
# uses: actions-rs/cargo@v1
|
||||
# with:
|
||||
# command: clippy
|
||||
# args: --locked --all-targets --all-features -- --allow clippy::unknown_clippy_lints
|
||||
# - name: Run tests
|
||||
# uses: actions-rs/cargo@v1
|
||||
# with:
|
||||
# command: test
|
||||
# args: --locked
|
||||
|
||||
build:
|
||||
name: ${{ matrix.job.target }} (${{ matrix.job.os }})
|
||||
runs-on: ${{ matrix.job.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
job:
|
||||
# - { target: aarch64-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true }
|
||||
# - { target: arm-unknown-linux-gnueabihf , os: ubuntu-20.04, use-cross: true }
|
||||
# - { target: arm-unknown-linux-musleabihf, os: ubuntu-20.04, use-cross: true }
|
||||
# - { target: i686-pc-windows-msvc , os: windows-2019 }
|
||||
# - { target: i686-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true }
|
||||
# - { target: i686-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
|
||||
# - { target: x86_64-apple-darwin , os: macos-10.15 }
|
||||
# - { target: x86_64-pc-windows-gnu , os: windows-2019 }
|
||||
# - { target: x86_64-pc-windows-msvc , os: windows-2019 }
|
||||
- { target: x86_64-unknown-linux-gnu , os: ubuntu-20.04 }
|
||||
# - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install prerequisites
|
||||
shell: bash
|
||||
run: |
|
||||
case ${{ matrix.job.target }} in
|
||||
x86_64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt install -y g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake ;;
|
||||
# arm-unknown-linux-*) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;;
|
||||
# aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;;
|
||||
esac
|
||||
|
||||
- name: Restore from cache and install vcpkg
|
||||
uses: lukka/run-vcpkg@v7
|
||||
with:
|
||||
setupOnly: true
|
||||
vcpkgGitCommitId: '1d4128f08e30cec31b94500840c7eca8ebc579cb'
|
||||
|
||||
- name: Install vcpkg dependencies
|
||||
run: |
|
||||
$VCPKG_ROOT/vcpkg install libvpx libyuv opus
|
||||
shell: bash
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: ${{ matrix.job.target }}
|
||||
override: true
|
||||
profile: minimal # minimal component installation (ie, no documentation)
|
||||
|
||||
- name: Show version information (Rust, cargo, GCC)
|
||||
shell: bash
|
||||
run: |
|
||||
gcc --version || true
|
||||
rustup -V
|
||||
rustup toolchain list
|
||||
rustup default
|
||||
cargo -V
|
||||
rustc -V
|
||||
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: ${{ matrix.job.use-cross }}
|
||||
command: build
|
||||
args: --locked --release --target=${{ matrix.job.target }}
|
||||
|
||||
# - name: Strip debug information from executable
|
||||
# id: strip
|
||||
# shell: bash
|
||||
# run: |
|
||||
# # Figure out suffix of binary
|
||||
# EXE_suffix=""
|
||||
# case ${{ matrix.job.target }} in
|
||||
# *-pc-windows-*) EXE_suffix=".exe" ;;
|
||||
# esac;
|
||||
|
||||
# # Figure out what strip tool to use if any
|
||||
# STRIP="strip"
|
||||
# case ${{ matrix.job.target }} in
|
||||
# arm-unknown-linux-*) STRIP="arm-linux-gnueabihf-strip" ;;
|
||||
# aarch64-unknown-linux-gnu) STRIP="aarch64-linux-gnu-strip" ;;
|
||||
# *-pc-windows-msvc) STRIP="" ;;
|
||||
# esac;
|
||||
|
||||
# # Setup paths
|
||||
# BIN_DIR="${{ env.CICD_INTERMEDIATES_DIR }}/stripped-release-bin/"
|
||||
# mkdir -p "${BIN_DIR}"
|
||||
# BIN_NAME="${{ env.PROJECT_NAME }}${EXE_suffix}"
|
||||
# BIN_PATH="${BIN_DIR}/${BIN_NAME}"
|
||||
|
||||
# # Copy the release build binary to the result location
|
||||
# cp "target/${{ matrix.job.target }}/release/${BIN_NAME}" "${BIN_DIR}"
|
||||
|
||||
# # Also strip if possible
|
||||
# if [ -n "${STRIP}" ]; then
|
||||
# "${STRIP}" "${BIN_PATH}"
|
||||
# fi
|
||||
|
||||
# # Let subsequent steps know where to find the (stripped) bin
|
||||
# echo ::set-output name=BIN_PATH::${BIN_PATH}
|
||||
# echo ::set-output name=BIN_NAME::${BIN_NAME}
|
||||
|
||||
- name: Set testing options
|
||||
id: test-options
|
||||
shell: bash
|
||||
run: |
|
||||
# test only library unit tests and binary for arm-type targets
|
||||
unset CARGO_TEST_OPTIONS
|
||||
unset CARGO_TEST_OPTIONS ; case ${{ matrix.job.target }} in arm-* | aarch64-*) CARGO_TEST_OPTIONS="--lib --bin ${PROJECT_NAME}" ;; esac;
|
||||
echo ::set-output name=CARGO_TEST_OPTIONS::${CARGO_TEST_OPTIONS}
|
||||
|
||||
- name: Build tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: ${{ matrix.job.use-cross }}
|
||||
command: build
|
||||
args: --locked --tests --target=${{ matrix.job.target }}
|
||||
|
||||
# - name: Run tests
|
||||
# uses: actions-rs/cargo@v1
|
||||
# with:
|
||||
# use-cross: ${{ matrix.job.use-cross }}
|
||||
# command: test
|
||||
# args: --locked --target=${{ matrix.job.target }} ${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}}
|
43
Cargo.lock
generated
43
Cargo.lock
generated
@ -352,6 +352,20 @@ dependencies = [
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-master"
|
||||
version = "3.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd1cb2f0df685eb4a61c656faeb6ef391ad776943d3723afb12bdcbceff824d"
|
||||
dependencies = [
|
||||
"objc",
|
||||
"objc-foundation",
|
||||
"objc_id",
|
||||
"winapi 0.3.9",
|
||||
"windows-win",
|
||||
"x11-clipboard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
version = "4.2.1"
|
||||
@ -2860,6 +2874,7 @@ dependencies = [
|
||||
"cc",
|
||||
"cfg-if 1.0.0",
|
||||
"clap",
|
||||
"clipboard-master",
|
||||
"cocoa",
|
||||
"core-foundation 0.9.1",
|
||||
"core-graphics",
|
||||
@ -3771,6 +3786,15 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-win"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d4243ec23afe4e9b4e668b3c0a0e973f1b8265f6a46223cfcbc16fd267480c0"
|
||||
dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.6.2"
|
||||
@ -3814,6 +3838,15 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
||||
|
||||
[[package]]
|
||||
name = "x11-clipboard"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b397ace6e980510de59a4fe3d4c758dffab231d6d747ce9fa1aba6b6035d5f32"
|
||||
dependencies = [
|
||||
"xcb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11rb"
|
||||
version = "0.8.1"
|
||||
@ -3826,6 +3859,16 @@ dependencies = [
|
||||
"winapi-wsapoll",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xcb"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62056f63138b39116f82a540c983cc11f1c90cd70b3d492a70c25eaa50bd22a6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.0"
|
||||
|
@ -51,6 +51,7 @@ mac_address = "1.1"
|
||||
sciter-rs = { git = "https://github.com/open-trade/rust-sciter", branch = "dyn" }
|
||||
ctrlc = "3.2"
|
||||
arboard = "2.0"
|
||||
clipboard-master = "3"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
#systray = { git = "https://github.com/open-trade/systray-rs" }
|
||||
|
@ -7,7 +7,7 @@ RUN git clone https://github.com/microsoft/vcpkg && cd vcpkg && git checkout 134
|
||||
RUN /vcpkg/bootstrap-vcpkg.sh -disableMetrics
|
||||
RUN /vcpkg/vcpkg --disable-metrics install libvpx libyuv opus
|
||||
|
||||
RUN groupadd -r user && useradd -r -g user user --home /home/user && mkdir -p /home/user && chown user /home/user
|
||||
RUN groupadd -r user && useradd -r -g user user --home /home/user && mkdir -p /home/user && chown user /home/user && echo "user ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/user
|
||||
WORKDIR /home/user
|
||||
RUN wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
|
||||
USER user
|
||||
|
@ -106,6 +106,10 @@ mv libsciter-gtk.so target/debug
|
||||
cargo run
|
||||
```
|
||||
|
||||
### Ändere Wayland zu X11 (Xorg)
|
||||
|
||||
RustDesk unterstützt "Wayland" nicht. Siehe [hier](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) um Xorg als Standard GNOME Session zu nutzen.
|
||||
|
||||
## Auf Docker Kompilieren
|
||||
|
||||
Beginne damit das Repository zu klonen und den Docker Container zu bauen:
|
||||
@ -136,10 +140,6 @@ target/release/rustdesk
|
||||
|
||||
Bitte gehe sicher, dass du diese Befehle vom Stammverzeichnis vom RustDesk Repository nutzt, sonst kann es passieren, dass das Programm die Ressourcen nicht finden kann. Bitte bedenke auch, dass Unterbefehle von Cargo, wie z.B. `install` oder `run` aktuell noch nicht unterstützt werden, da sie das Programm innerhalb des Containers starten oder installieren würden, anstatt auf deinem eigentlichen System.
|
||||
|
||||
### Ändere Wayland zu X11 (Xorg)
|
||||
|
||||
RustDesk unterstützt "Wayland" nicht. Siehe [hier](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) um Xorg als Standard GNOME Session zu nutzen.
|
||||
|
||||
## Dateistruktur
|
||||
|
||||
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: Video Codec, Konfiguration, TCP/UDP Wrapper, Protokoll Puffer, fs Funktionen für Dateitransfer, und ein paar andere nützliche Funktionen
|
||||
|
@ -104,6 +104,10 @@ mv libsciter-gtk.so target/debug
|
||||
cargo run
|
||||
```
|
||||
|
||||
### Cambia Wayland a X11 (Xorg)
|
||||
|
||||
RustDesk no soporta Wayland. Comprueba [aquí](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) para configurar Xorg en la sesión por defecto de GNOME.
|
||||
|
||||
## Como compilar con Docker
|
||||
|
||||
Empieza clonando el repositorio y compilando el contenedor de docker:
|
||||
@ -134,10 +138,6 @@ target/release/rustdesk
|
||||
|
||||
Por favor, asegurate de que estás ejecutando estos comandos desde la raíz del repositorio de RustDesk, de lo contrario la aplicación puede ser incapaz de encontrar los recursos necesarios. También hay que tener en cuenta que otros subcomandos de carga como `install` o `run` no estan actualmente soportados via este metodo y podrían requerir ser instalados dentro del contenedor y no en el host.
|
||||
|
||||
### Cambia Wayland a X11 (Xorg)
|
||||
|
||||
RustDesk no soporta Wayland. Comprueba [aquí](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) para configurar Xorg en la sesión por defecto de GNOME.
|
||||
|
||||
## Estructura de archivos
|
||||
|
||||
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: video codec, configuración, tcp/udp wrapper, protobuf, fs funciones para transferencia de ficheros, y alguna función de utilidad.
|
||||
|
@ -104,6 +104,10 @@ mv libsciter-gtk.so target/debug
|
||||
Exécution du cargo
|
||||
```
|
||||
|
||||
### Changer Wayland en X11 (Xorg)
|
||||
|
||||
RustDesk ne supporte pas Wayland. Lisez [cela](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) pour configurer Xorg comme la session GNOME par défaut.
|
||||
|
||||
## Comment construire avec Docker
|
||||
|
||||
Commencez par cloner le dépôt et construire le conteneur Docker :
|
||||
@ -134,10 +138,6 @@ target/release/rustdesk
|
||||
|
||||
Veuillez vous assurer que vous exécutez ces commandes à partir de la racine du référentiel RustDesk, sinon l'application ne pourra pas trouver les ressources requises. Notez également que les autres sous-commandes de cargo telles que `install` ou `run` ne sont pas actuellement supportées par cette méthode car elles installeraient ou exécuteraient le programme à l'intérieur du conteneur au lieu de l'hôte.
|
||||
|
||||
### Changer Wayland en X11 (Xorg)
|
||||
|
||||
RustDesk ne supporte pas Wayland. Lisez [cela](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) pour configurer Xorg comme la session GNOME par défaut.
|
||||
|
||||
## Structure du projet
|
||||
|
||||
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)** : codec vidéo, config, wrapper tcp/udp, protobuf, fonctions fs pour le transfert de fichiers, et quelques autres fonctions utilitaires.
|
||||
|
@ -105,6 +105,10 @@ mv libsciter-gtk.so target/debug
|
||||
cargo run
|
||||
```
|
||||
|
||||
### Zmień Wayland na X11 (Xorg)
|
||||
|
||||
RustDesk nie obsługuje Waylanda. Sprawdź [this](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) by skonfigurować Xorg jako domyślną sesję GNOME.
|
||||
|
||||
## Jak kompilować za pomocą Dockera
|
||||
|
||||
Rozpocznij od sklonowania repozytorium i stworzenia kontenera docker:
|
||||
@ -135,10 +139,6 @@ target/release/rustdesk
|
||||
|
||||
Upewnij się, że uruchamiasz te polecenia z katalogu głównego repozytorium RustDesk, w przeciwnym razie aplikacja może nie być w stanie znaleźć wymaganych zasobów. Należy również pamiętać, że inne podpolecenia ładowania, takie jak `install` lub `run` nie są obecnie obsługiwane za pomocą tej metody, ponieważ instalowałyby lub uruchamiały program wewnątrz kontenera zamiast na hoście.
|
||||
|
||||
### Zmień Wayland na X11 (Xorg)
|
||||
|
||||
RustDesk nie obsługuje Waylanda. Sprawdź [this](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) by skonfigurować Xorg jako domyślną sesję GNOME.
|
||||
|
||||
## Struktura plików
|
||||
|
||||
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: kodek wideo, config, wrapper tcp/udp, protobuf, funkcje fs do transferu plików i kilka innych funkcji użytkowych
|
||||
|
10
README-ZH.md
10
README-ZH.md
@ -105,6 +105,11 @@ mv libsciter-gtk.so target/debug
|
||||
cargo run
|
||||
```
|
||||
|
||||
### 把 Wayland 修改成 X11 (Xorg)
|
||||
|
||||
RustDesk 暂时不支持 Wayland,不过正在积极开发中.
|
||||
请查看[this](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/)配置 X11.
|
||||
|
||||
## 使用 Docker 编译
|
||||
|
||||
首先克隆存储库并构建 docker 容器:
|
||||
@ -186,11 +191,6 @@ target/release/rustdesk
|
||||
请确保您从 RustDesk 存储库的根目录运行这些命令,否则应用程序可能无法找到所需的资源。另请注意,此方法当前不支持其他`Cargo`子命令,
|
||||
例如 `install` 或 `run`,因为运行在容器里,而不是宿主机上。
|
||||
|
||||
### 把 Wayland 修改成 X11 (Xorg)
|
||||
|
||||
RustDesk 暂时不支持 Wayland,不过正在积极开发中.
|
||||
请查看[this](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/)配置 X11.
|
||||
|
||||
## 文件结构
|
||||
|
||||
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: 视频编解码, 配置, tcp/udp 封装, protobuf, 文件传输相关文件系统操作函数, 以及一些其他实用函数
|
||||
|
@ -105,6 +105,10 @@ mv libsciter-gtk.so target/debug
|
||||
VCPKG_ROOT=$HOME/vcpkg cargo run
|
||||
```
|
||||
|
||||
### Change Wayland to X11 (Xorg)
|
||||
|
||||
RustDesk does not support Wayland. Check [this](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) to configuring Xorg as the default GNOME session.
|
||||
|
||||
## How to build with Docker
|
||||
|
||||
Begin by cloning the repository and building the docker container:
|
||||
@ -135,10 +139,6 @@ target/release/rustdesk
|
||||
|
||||
Please ensure that you are running these commands from the root of the RustDesk repository, otherwise the application may be unable to find the required resources. Also note that other cargo subcommands such as `install` or `run` are not currently supported via this method as they would install or run the program inside the container instead of the host.
|
||||
|
||||
### Change Wayland to X11 (Xorg)
|
||||
|
||||
RustDesk does not support Wayland. Check [this](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) to configuring Xorg as the default GNOME session.
|
||||
|
||||
## File Structure
|
||||
|
||||
- **[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
|
||||
|
@ -1,13 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$(id -u)" != "${PUID:-1000}" ] || [ "$(id -g)" != "${PGID:-1000}" ]; then
|
||||
usermod -o -u "${PUID:-1000}" user
|
||||
groupmod -o -g "${PGID:-1000}" user
|
||||
chown -R user /home/user
|
||||
sudo -u user /entrypoint $@
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd $HOME/rustdesk
|
||||
. $HOME/.cargo/env
|
||||
|
||||
|
@ -48,6 +48,7 @@ message PunchHoleSent {
|
||||
string id = 2;
|
||||
string relay_server = 3;
|
||||
NatType nat_type = 4;
|
||||
string version = 5;
|
||||
}
|
||||
|
||||
message RegisterPk {
|
||||
@ -110,6 +111,7 @@ message RelayResponse {
|
||||
bytes pk = 5;
|
||||
}
|
||||
string refuse_reason = 6;
|
||||
string version = 7;
|
||||
}
|
||||
|
||||
message SoftwareUpdate { string url = 1; }
|
||||
@ -128,6 +130,7 @@ message LocalAddr {
|
||||
bytes local_addr = 2;
|
||||
string relay_server = 3;
|
||||
string id = 4;
|
||||
string version = 5;
|
||||
}
|
||||
|
||||
message RendezvousMessage {
|
||||
|
@ -1,6 +1,6 @@
|
||||
pub use arboard::Clipboard as ClipboardContext;
|
||||
use hbb_common::{
|
||||
allow_err,
|
||||
allow_err, bail,
|
||||
compress::{compress as compress_func, decompress},
|
||||
config::{Config, COMPRESS_LEVEL, RENDEZVOUS_TIMEOUT},
|
||||
log,
|
||||
@ -240,6 +240,10 @@ async fn test_nat_type_() -> ResultType<bool> {
|
||||
let rendezvous_server = get_rendezvous_server(100).await;
|
||||
let server1 = rendezvous_server;
|
||||
let mut server2 = server1;
|
||||
if server1.port() == 0 { // offline
|
||||
// avoid overflow crash
|
||||
bail!("Offline");
|
||||
}
|
||||
server2.set_port(server1.port() - 1);
|
||||
let mut msg_out = RendezvousMessage::new();
|
||||
let serial = Config::get_serial();
|
||||
|
@ -285,6 +285,7 @@ impl RendezvousMediator {
|
||||
let mut msg_out = Message::new();
|
||||
let mut rr = RelayResponse {
|
||||
socket_addr,
|
||||
version: crate::VERSION.to_owned(),
|
||||
..Default::default()
|
||||
};
|
||||
if initiate {
|
||||
@ -321,6 +322,7 @@ impl RendezvousMediator {
|
||||
socket_addr: AddrMangle::encode(peer_addr),
|
||||
local_addr: AddrMangle::encode(local_addr),
|
||||
relay_server,
|
||||
version: crate::VERSION.to_owned(),
|
||||
..Default::default()
|
||||
});
|
||||
let bytes = msg_out.write_to_bytes()?;
|
||||
@ -359,6 +361,7 @@ impl RendezvousMediator {
|
||||
id: Config::get_id(),
|
||||
relay_server,
|
||||
nat_type: nat_type.into(),
|
||||
version: crate::VERSION.to_owned(),
|
||||
..Default::default()
|
||||
});
|
||||
let bytes = msg_out.write_to_bytes()?;
|
||||
|
@ -3,49 +3,102 @@ pub use crate::common::{
|
||||
check_clipboard, ClipboardContext, CLIPBOARD_INTERVAL as INTERVAL, CLIPBOARD_NAME as NAME,
|
||||
CONTENT,
|
||||
};
|
||||
|
||||
struct State {
|
||||
ctx: Option<ClipboardContext>,
|
||||
}
|
||||
|
||||
impl Default for State {
|
||||
fn default() -> Self {
|
||||
let ctx = match ClipboardContext::new() {
|
||||
Ok(ctx) => Some(ctx),
|
||||
Err(err) => {
|
||||
log::error!("Failed to start {}: {}", NAME, err);
|
||||
None
|
||||
}
|
||||
};
|
||||
Self { ctx }
|
||||
}
|
||||
}
|
||||
|
||||
impl super::service::Reset for State {
|
||||
fn reset(&mut self) {
|
||||
*CONTENT.lock().unwrap() = Default::default();
|
||||
}
|
||||
}
|
||||
use clipboard_master::{CallbackResult, ClipboardHandler, Master};
|
||||
use hbb_common::{anyhow, ResultType};
|
||||
use std::{
|
||||
io, sync,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
mpsc::SyncSender,
|
||||
},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
pub fn new() -> GenericService {
|
||||
let sp = GenericService::new(NAME, true);
|
||||
sp.repeat::<State, _>(INTERVAL, run);
|
||||
sp.run::<_>(listen::run);
|
||||
sp
|
||||
}
|
||||
|
||||
fn run(sp: GenericService, state: &mut State) -> ResultType<()> {
|
||||
if let Some(ctx) = state.ctx.as_mut() {
|
||||
if let Some(msg) = check_clipboard(ctx, None) {
|
||||
sp.send(msg);
|
||||
}
|
||||
sp.snapshot(|sps| {
|
||||
let txt = crate::CONTENT.lock().unwrap().clone();
|
||||
if !txt.is_empty() {
|
||||
let msg_out = crate::create_clipboard_msg(txt);
|
||||
sps.send_shared(Arc::new(msg_out));
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
mod listen {
|
||||
use super::*;
|
||||
|
||||
static RUNNING: AtomicBool = AtomicBool::new(true);
|
||||
static WAIT: Duration = Duration::from_millis(1500);
|
||||
|
||||
struct ClipHandle {
|
||||
tx: SyncSender<()>,
|
||||
}
|
||||
|
||||
impl ClipboardHandler for ClipHandle {
|
||||
fn on_clipboard_change(&mut self) -> CallbackResult {
|
||||
if !RUNNING.load(Ordering::SeqCst) {
|
||||
return CallbackResult::Stop;
|
||||
}
|
||||
|
||||
let _ = self.tx.send(());
|
||||
CallbackResult::Next
|
||||
}
|
||||
|
||||
fn on_clipboard_error(&mut self, error: io::Error) -> CallbackResult {
|
||||
if !RUNNING.load(Ordering::SeqCst) {
|
||||
CallbackResult::Stop
|
||||
} else {
|
||||
CallbackResult::StopWithError(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn run(sp: GenericService) -> ResultType<()> {
|
||||
let mut ctx = match ClipboardContext::new() {
|
||||
Ok(ctx) => ctx,
|
||||
Err(err) => {
|
||||
log::error!("Failed to start {}: {}", NAME, err);
|
||||
return Err(anyhow::Error::from(err));
|
||||
}
|
||||
};
|
||||
|
||||
if !RUNNING.load(Ordering::SeqCst) {
|
||||
RUNNING.store(true, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
let (tx, rx) = sync::mpsc::sync_channel(12);
|
||||
let listener = tokio::spawn(async {
|
||||
log::info!("Clipboard listener running!");
|
||||
let _ = Master::new(ClipHandle { tx }).run();
|
||||
});
|
||||
|
||||
while sp.ok() {
|
||||
if let Ok(_) = rx.recv_timeout(WAIT) {
|
||||
if let Some(msg) = check_clipboard(&mut ctx, None) {
|
||||
sp.send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
sp.snapshot(|sps| {
|
||||
let txt = crate::CONTENT.lock().unwrap().clone();
|
||||
if !txt.is_empty() {
|
||||
let msg_out = crate::create_clipboard_msg(txt);
|
||||
sps.send_shared(Arc::new(msg_out));
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
|
||||
RUNNING.store(false, Ordering::SeqCst);
|
||||
trigger(&mut ctx);
|
||||
let _ = listener.await;
|
||||
log::info!("Clipboard listener stopped!");
|
||||
|
||||
*CONTENT.lock().unwrap() = Default::default();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn trigger(ctx: &mut ClipboardContext) {
|
||||
let _ = match ctx.get_text() {
|
||||
Ok(text) => ctx.set_text(text),
|
||||
Err(_) => ctx.set_text(Default::default()),
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
13
src/ui.rs
13
src/ui.rs
@ -333,9 +333,21 @@ impl UI {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*self.2.lock().unwrap() = m.clone();
|
||||
ipc::set_options(m).ok();
|
||||
}
|
||||
|
||||
fn set_option(&self, key: String, value: String) {
|
||||
let mut options = self.2.lock().unwrap();
|
||||
if value.is_empty() {
|
||||
options.remove(&key);
|
||||
} else {
|
||||
options.insert(key, value);
|
||||
}
|
||||
ipc::set_options(options.clone()).ok();
|
||||
}
|
||||
|
||||
fn install_path(&mut self) -> String {
|
||||
#[cfg(windows)]
|
||||
return crate::platform::windows::get_install_info().1;
|
||||
@ -587,6 +599,7 @@ impl sciter::EventHandler for UI {
|
||||
fn test_if_valid_server(String);
|
||||
fn get_sound_inputs();
|
||||
fn set_options(Value);
|
||||
fn set_option(String, String);
|
||||
fn get_software_update_url();
|
||||
fn get_new_version();
|
||||
fn get_version();
|
||||
|
@ -257,6 +257,10 @@ handler.msgbox = function(type, title, text, callback=null, height=180, width=50
|
||||
self.timer(150ms, function() { msgbox(type, title, text, callback, height, width, retry); });
|
||||
}
|
||||
|
||||
handler.block_msgbox = function(type, title, text, callback=null, height=180, width=500, retry=0) {
|
||||
msgbox(type, title, text, callback, height, width, retry);
|
||||
}
|
||||
|
||||
var reconnectTimeout = 1;
|
||||
handler.msgbox_retry = function(type, title, text, hasRetry, callback=null, height=180, width=500) {
|
||||
handler.msgbox(type, title, text, callback, height, width, hasRetry ? reconnectTimeout : 0);
|
||||
|
@ -30,6 +30,7 @@ table > thead {
|
||||
}
|
||||
|
||||
table > tbody {
|
||||
behavior: select-multiple;
|
||||
overflow-y: scroll-indicator;
|
||||
size: *;
|
||||
background: white;
|
||||
@ -85,6 +86,15 @@ table.has_current tr:current /* current row */
|
||||
background-color: color(accent);
|
||||
}
|
||||
|
||||
table.has_current tbody tr:checked
|
||||
{
|
||||
background-color: color(accent);
|
||||
}
|
||||
|
||||
table.has_current tbody tr:checked td {
|
||||
color: highlighttext;
|
||||
}
|
||||
|
||||
table td
|
||||
{
|
||||
padding: 4px;
|
||||
|
@ -374,7 +374,7 @@ class FolderView : Reactor.Component {
|
||||
path = this.joinPath(entry.name);
|
||||
}
|
||||
var tm = entry.time ? new Date(entry.time.toFloat() * 1000.).toLocaleString() : 0;
|
||||
return <tr>
|
||||
return <tr role="option">
|
||||
<td type={entry.type} filename={path}></td>
|
||||
<td>{entry.name}</td>
|
||||
<td value={entry.time || 0}>{tm || ""}</td>
|
||||
@ -401,20 +401,31 @@ class FolderView : Reactor.Component {
|
||||
}
|
||||
|
||||
event click $(.trash) () {
|
||||
var row = this.getCurrentRow();
|
||||
if (!row) return;
|
||||
var path = row[0];
|
||||
var type = row[1];
|
||||
var new_history = [];
|
||||
for (var i = 0; i < this.history.length; ++i) {
|
||||
var h = this.history[i];
|
||||
if ((h + this.sep()).indexOf(path + this.sep()) == -1) new_history.push(h);
|
||||
var rows = this.getCurrentRows();
|
||||
if (!rows || rows.length == 0) return;
|
||||
|
||||
var delete_dirs = new Array();
|
||||
|
||||
for (var i = 0; i < rows.length; ++i) {
|
||||
var row = rows[i];
|
||||
|
||||
var path = row[0];
|
||||
var type = row[1];
|
||||
|
||||
var new_history = [];
|
||||
for (var j = 0; j < this.history.length; ++j) {
|
||||
var h = this.history[j];
|
||||
if ((h + this.sep()).indexOf(path + this.sep()) == -1) new_history.push(h);
|
||||
}
|
||||
this.history = new_history;
|
||||
if (type == 1) {
|
||||
delete_dirs.push(path);
|
||||
} else {
|
||||
confirmDelete(path, this.is_remote);
|
||||
}
|
||||
}
|
||||
this.history = new_history;
|
||||
if (type == 1) {
|
||||
file_transfer.job_table.addDelDir(path, this.is_remote);
|
||||
} else {
|
||||
confirmDelete(path, this.is_remote);
|
||||
for (var i = 0; i < delete_dirs.length; ++i) {
|
||||
file_transfer.job_table.addDelDir(delete_dirs[i], this.is_remote);
|
||||
}
|
||||
}
|
||||
|
||||
@ -463,10 +474,28 @@ class FolderView : Reactor.Component {
|
||||
return [this.joinPath(name), type];
|
||||
}
|
||||
|
||||
function getCurrentRows() {
|
||||
var rows = this.table.getCurrentRows();
|
||||
if (!rows || rows.length== 0) return;
|
||||
|
||||
var records = new Array();
|
||||
|
||||
for (var i = 0; i < rows.length; ++i) {
|
||||
var name = rows[i][1].text;
|
||||
if (!name || name == "..") continue;
|
||||
|
||||
var type = rows[i][0].attributes["type"];
|
||||
records.push([this.joinPath(name), type]);
|
||||
}
|
||||
return records;
|
||||
}
|
||||
|
||||
event click $(.send) () {
|
||||
var cur = this.getCurrentRow();
|
||||
if (!cur) return;
|
||||
file_transfer.job_table.send(cur[0], this.is_remote);
|
||||
var rows = this.getCurrentRows();
|
||||
if (!rows || rows.length == 0) return;
|
||||
for (var i = 0; i < rows.length; ++i) {
|
||||
file_transfer.job_table.send(rows[i][0], this.is_remote);
|
||||
}
|
||||
}
|
||||
|
||||
event change $(.select-dir) (_, el) {
|
||||
@ -570,7 +599,7 @@ var deleting_single_file_jobs = {};
|
||||
var create_dir_jobs = {}
|
||||
|
||||
function confirmDelete(path, is_remote) {
|
||||
handler.msgbox("custom-skip", "Confirm Delete", "<div .form> \
|
||||
handler.block_msgbox("custom-skip", "Confirm Delete", "<div .form> \
|
||||
<div>Are you sure you want to delete this file?</div> \
|
||||
<div.ellipsis style=\"font-weight: bold;\">" + path + "</div> \
|
||||
</div>", function(res=null) {
|
||||
@ -590,7 +619,7 @@ handler.confirmDeleteFiles = function(id, i, name) {
|
||||
if (i >= n) return;
|
||||
var file_path = job.path;
|
||||
if (name) file_path += handler.get_path_sep(job.is_remote) + name;
|
||||
handler.msgbox("custom-skip", "Confirm Delete", "<div .form> \
|
||||
handler.block_msgbox("custom-skip", "Confirm Delete", "<div .form> \
|
||||
<div>Deleting #" + (i + 1) + " of " + n + " files.</div> \
|
||||
<div>Are you sure you want to delete this file?</div> \
|
||||
<div.ellipsis style=\"font-weight: bold;\" .text>" + name + "</div> \
|
||||
|
@ -24,6 +24,11 @@ class Grid: Behavior {
|
||||
{
|
||||
return this.$(tbody>tr:current);
|
||||
}
|
||||
|
||||
function getCurrentRows()
|
||||
{
|
||||
return this.$$(tbody>tr:checked);
|
||||
}
|
||||
|
||||
function getCurrentColumn()
|
||||
{
|
||||
|
@ -40,9 +40,7 @@ class ConnectStatus: Reactor.Component {
|
||||
}
|
||||
|
||||
event click $(.connect-status .link) () {
|
||||
var options = handler.get_options();
|
||||
options["stop-service"] = "";
|
||||
handler.set_options(options);
|
||||
handler.set_option("stop-service", "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +136,6 @@ function createNewConnect(id, type) {
|
||||
|
||||
var myIdMenu;
|
||||
var audioInputMenu;
|
||||
var configOptions = {};
|
||||
class AudioInputs: Reactor.Component {
|
||||
function this() {
|
||||
audioInputMenu = this;
|
||||
@ -167,7 +164,7 @@ class AudioInputs: Reactor.Component {
|
||||
}
|
||||
|
||||
function get_value() {
|
||||
return configOptions["audio-input"] || this.get_default();
|
||||
return handler.get_option("audio-input") || this.get_default();
|
||||
}
|
||||
|
||||
function toggleMenuState() {
|
||||
@ -182,8 +179,7 @@ class AudioInputs: Reactor.Component {
|
||||
var v = me.id;
|
||||
if (v == this.get_value()) return;
|
||||
if (v == this.get_default()) v = "";
|
||||
configOptions["audio-input"] = v;
|
||||
handler.set_options(configOptions);
|
||||
handler.set_option("audio-input", v);
|
||||
this.toggleMenuState();
|
||||
}
|
||||
}
|
||||
@ -223,7 +219,6 @@ class MyIdMenu: Reactor.Component {
|
||||
|
||||
event click $(svg#menu) (_, me) {
|
||||
audioInputMenu.update({ show: true });
|
||||
configOptions = handler.get_options();
|
||||
this.toggleMenuState();
|
||||
var menu = $(menu#config-options);
|
||||
me.popup(menu);
|
||||
@ -232,7 +227,7 @@ class MyIdMenu: Reactor.Component {
|
||||
function toggleMenuState() {
|
||||
for (var el in $$(menu#config-options>li)) {
|
||||
if (el.id && el.id.indexOf("enable-") == 0) {
|
||||
var enabled = configOptions[el.id] != "N";
|
||||
var enabled = handler.get_option(el.id) != "N";
|
||||
el.attributes.toggleClass("selected", enabled);
|
||||
el.attributes.toggleClass("line-through", !enabled);
|
||||
}
|
||||
@ -241,11 +236,10 @@ class MyIdMenu: Reactor.Component {
|
||||
|
||||
event click $(menu#config-options>li) (_, me) {
|
||||
if (me.id && me.id.indexOf("enable-") == 0) {
|
||||
configOptions[me.id] = configOptions[me.id] == "N" ? "" : "N";
|
||||
handler.set_options(configOptions);
|
||||
handler.set_option(me.id, handler.get_option(me.id) == "N" ? "" : "N");
|
||||
}
|
||||
if (me.id == "whitelist") {
|
||||
var old_value = (configOptions["whitelist"] || "").split(",").join("\n");
|
||||
var old_value = handler.get_option("whitelist").split(",").join("\n");
|
||||
handler.msgbox("custom-whitelist", "IP Whitelisting", "<div .form> \
|
||||
<textarea spellcheck=\"false\" name=\"text\" novalue=\"0.0.0.0\" style=\"overflow: scroll-indicator; height: 160px; font-size: 1.2em; padding: 0.5em;\">" + old_value + "</textarea>\
|
||||
</div> \
|
||||
@ -253,7 +247,7 @@ class MyIdMenu: Reactor.Component {
|
||||
if (!res) return;
|
||||
var value = (res.text || "").trim();
|
||||
if (value) {
|
||||
var values = value.split(/[\s,;]+/g);
|
||||
var values = value.split(/[\s,;\n]+/g);
|
||||
for (var ip in values) {
|
||||
if (!ip.match(/^\d+\.\d+\.\d+\.\d+$/)) {
|
||||
return "Invalid ip: " + ip;
|
||||
@ -262,11 +256,11 @@ class MyIdMenu: Reactor.Component {
|
||||
value = values.join("\n");
|
||||
}
|
||||
if (value == old_value) return;
|
||||
configOptions["whitelist"] = value.replace("\n", ",");
|
||||
stdout.println("whitelist updated");
|
||||
handler.set_options(configOptions);
|
||||
handler.set_option("whitelist", value.replace("\n", ","));
|
||||
}, 300);
|
||||
} else if (me.id == "custom-server") {
|
||||
var configOptions = handler.get_options();
|
||||
var old_relay = configOptions["relay-server"] || "";
|
||||
var old_id = configOptions["custom-rendezvous-server"] || "";
|
||||
handler.msgbox("custom-server", "ID/Relay Server", "<div .form> \
|
||||
@ -293,8 +287,7 @@ class MyIdMenu: Reactor.Component {
|
||||
} else if (me.id == "forum") {
|
||||
handler.open_url("https:://forum.rustdesk.com");
|
||||
} else if (me.id == "stop-service") {
|
||||
configOptions["stop-service"] = service_stopped ? "" : "Y";
|
||||
handler.set_options(configOptions);
|
||||
handler.set_option("stop-service", service_stopped ? "" : "Y");
|
||||
} else if (me.id == "about") {
|
||||
var name = handler.get_app_name();
|
||||
handler.msgbox("custom-nocancel-nook-hasclose", "About " + name, "<div style='line-height: 2em'> \
|
||||
|
Loading…
x
Reference in New Issue
Block a user