Compare commits

..

654 Commits
1.1.4 ... 1.1.9

Author SHA1 Message Date
RustDesk
d716e2b40c Merge pull request #474 from ripp2003/patch-1
Update fr.rs
2022-05-02 16:07:54 +08:00
ripp2003
c9cd57e178 Update fr.rs
Do you accept was not trad
2022-05-02 07:45:10 +02:00
rustdesk
388dcbeb6d comments 2022-05-02 04:41:45 +08:00
rustdesk
a8ad9e9c46 fix format 2022-05-02 03:03:15 +08:00
rustdesk
8a3da687c1 help on mac permissons 2022-05-02 02:44:16 +08:00
rustdesk
0e4e7fcb9b fix cm 2022-05-02 00:02:41 +08:00
rustdesk
663c5bc355 code sign mac 2022-05-01 23:39:03 +08:00
rustdesk
7235756603 fix config sync 2022-05-01 00:50:54 +08:00
rustdesk
f6612d39bf Merge branch 'master' of github.com-rustdesk:rustdesk/rustdesk 2022-04-30 16:43:01 +08:00
rustdesk
a9ada68bfc workaround for shit sciter about style 2022-04-30 16:42:49 +08:00
rustdesk
f21788b967 fix compile warn on win 2022-04-30 14:59:21 +08:00
rustdesk
f90f83fbda more friendly to 0 connections if any unknow happend 2022-04-29 23:32:10 +08:00
rustdesk
1235edb239 found one blank cm, still not find reason 2022-04-29 19:40:53 +08:00
rustdesk
e2c9b78254 mac tray work 2022-04-29 16:21:18 +08:00
rustdesk
8df1e42977 hide icon after initialization before close is useless 2022-04-29 10:40:00 +08:00
rustdesk
69b3f6660a fix ci 2022-04-28 21:54:27 +08:00
rustdesk
c1f5c20e94 https://github.com/rustdesk/rustdesk/issues/77 mac tray, still no find good way to open rustdesk from finder after tray
shown
2022-04-28 21:32:44 +08:00
rustdesk
de44e45ed6 small tweak 2022-04-28 12:10:14 +08:00
rustdesk
0b6155bab8 looks robust now 2022-04-28 04:22:46 +08:00
rustdesk
8995011d45 still not robust 2022-04-28 03:25:39 +08:00
rustdesk
bbe902d92e improve mac service 2022-04-27 19:21:38 +08:00
rustdesk
33c6095eca autofocus chat box input 2022-04-27 01:07:00 +08:00
rustdesk
e66ccdca9d comment for another service implementation 2022-04-26 14:09:47 +08:00
rustdesk
36607bf8b0 fix snap CI 2022-04-26 11:43:16 +08:00
rustdesk
4dfd57ea19 missed file 2022-04-26 11:20:02 +08:00
rustdesk
3566b0ee7a new mac service and local config 2022-04-26 11:19:45 +08:00
rustdesk
05ac26e5fe fix long remote-id style 2022-04-26 00:46:21 +08:00
rustdesk
f1d187739c https://github.com/rustdesk/rustdesk/issues/461 2022-04-24 23:54:05 +08:00
rustdesk
e2161bcc43 fix last PR 2022-04-24 18:11:52 +08:00
RustDesk
ec700ad37d Merge pull request #456 from xxrlzzz/optimize_appbar
Optimize appbar for macos
2022-04-24 17:21:21 +08:00
xxrl
81cd079faa Fix ui issue 2022-04-24 17:15:20 +08:00
RustDesk
7854ad5ee1 Merge pull request #460 from Redion/patch-2
Update README-RU.md
2022-04-24 15:08:01 +08:00
Radion Mynayev
65b335177a Update README-RU.md 2022-04-24 03:04:16 -04:00
rustdesk
eaa481cbea fix transparent cursor 2022-04-24 14:53:19 +08:00
rustdesk
4d5d0a4c62 improve video, ignore same image 2022-04-24 02:50:28 +08:00
rustdesk
264db496ff fix video service 2022-04-24 02:43:00 +08:00
rustdesk
f42a77ad22 fix lock screen for mac and linux 2022-04-24 02:37:27 +08:00
rustdesk
6bc0c3ce98 fix CI 2022-04-23 02:51:54 +08:00
rustdesk
ae74570ab8 fix CI 2022-04-23 02:29:11 +08:00
rustdesk
5bf8e8f001 change linux audio playback from cpal to pulse, because stupid cpal 100% cpu usage problem 2022-04-23 02:17:33 +08:00
xxrl
cfa0c1039c Optimize appbar for macos 2022-04-22 23:41:12 +08:00
rustdesk
aa7779bcf7 pynput version 2022-04-22 12:16:25 +08:00
rustdesk
5d143f57d7 SystemTime::now not work stable on my win7 32, change to Instant 2022-04-22 02:05:11 +08:00
rustdesk
f8fe47d53f fix snap CI 2022-04-21 22:16:15 +08:00
rustdesk
1e120eef18 async logger holder 2022-04-21 21:51:53 +08:00
rustdesk
ccffa14450 fix chat window focus problem and update version number https://github.com/rustdesk/rustdesk/issues/443 2022-04-20 20:44:48 +08:00
rustdesk
d858790170 trans 2022-04-20 17:53:43 +08:00
rustdesk
19468cdbcd wordy 2022-04-20 17:46:21 +08:00
rustdesk
c79c55d643 fix trans 2022-04-20 15:53:13 +08:00
rustdesk
4829b87546 trans 2022-04-20 15:45:33 +08:00
rustdesk
605a52aebb snap readme 2022-04-19 18:45:19 +08:00
RustDesk
da166223bc Merge pull request #450 from Kingtous/master
Feat: Build RustDesk by Snap
2022-04-19 17:00:26 +08:00
kingtous
fef8b0f246 opt: README.md snap connect pulseaudio 2022-04-19 16:45:03 +08:00
kingtous
11086ffa49 fix: libsciter download url 2022-04-19 15:18:52 +08:00
kingtous
f000d0c4ca fix: override pull to inline sciter 2022-04-19 15:10:15 +08:00
kingtous
88107f342d fix: change loginctl priviledge 2022-04-19 14:57:37 +08:00
kingtous
9dff6ee649 add: snap info 2022-04-19 14:46:46 +08:00
kingtous
8f4adab3c8 feat: snapcraft files 2022-04-19 14:46:18 +08:00
kingtous
92be77cf88 add: snap stage deps 2022-04-19 13:56:03 +08:00
rustdesk
885d3a6651 desktop 2022-04-19 12:29:24 +08:00
rustdesk
c0af51e1bd fix wrong link 2022-04-19 10:17:44 +08:00
rustdesk
f95f9e408a workaround for wrong password input hanging 2022-04-18 23:41:43 +08:00
rustdesk
915edf49ab alternative libsciter.so path 2022-04-18 15:45:12 +08:00
rustdesk
4e2a44e392 package script 2022-04-18 15:37:35 +08:00
rustdesk
bbdf3fc9a3 fix mouse out for android 2022-04-17 23:35:53 +08:00
rustdesk
110d63f526 comment out biased 2022-04-16 12:12:34 +08:00
rustdesk
75c9a8c561 remote min size, android icon and scrap memory safety 2022-04-14 20:44:43 +08:00
rustdesk
609996005f STRIDE_ALIGN 16 -> 64 2022-04-12 23:31:42 +08:00
RustDesk
aeb2846d15 Merge pull request #445 from Redion/patch-1
Update ru.rs
2022-04-11 10:26:46 +08:00
Radion Mynayev
f915ab3e79 Update ru.rs
Corrected some Russian translations
2022-04-11 11:23:24 +09:00
rustdesk
8d1f1a9ab4 TouchPad -> Mouse 2022-04-08 18:29:40 +08:00
rustdesk
fa2407d857 fix remote_dir 2022-04-07 22:13:30 +08:00
rustdesk
840413db5f more trans 2022-04-06 10:51:24 +08:00
RustDesk
f370c60d06 Update lang.rs 2022-04-06 10:26:09 +08:00
RustDesk
0a9a7e3090 Merge pull request #441 from mateusauler/translate-ptbr
Translate to Portuguese (Brazil)
2022-04-06 10:18:58 +08:00
Mateus Auler
f7f0146c85 Translate README to Portuguese (Brazil)
Signed-off-by: Mateus Auler <mateusauler@protonmail.com>
2022-04-05 20:31:32 -03:00
Mateus Auler
a29de132a3 Translate UI to Portuguese (Brazil)
Signed-off-by: Mateus Auler <mateusauler@protonmail.com>
2022-04-05 19:05:13 -03:00
rustdesk
6d122d8aef smaller letter size 2022-04-04 15:00:26 +08:00
rustdesk
fb98209008 trans 2022-04-04 14:09:54 +08:00
rustdesk
a56aa08a66 fix file delete bugs 2022-03-28 19:05:12 +08:00
rustdesk
3ea33f7203 improve file write to cm 2022-03-26 03:05:15 +08:00
rustdesk
75c9bbb30f refactor IdPk 2022-03-26 00:06:06 +08:00
rustdesk
1c84fc3786 default relay_server 2022-03-25 18:39:06 +08:00
rustdesk
08330cdaeb longer test_nat timeout 2022-03-25 17:32:32 +08:00
rustdesk
908a7071a7 fix trans 2022-03-24 15:27:06 +08:00
rustdesk
3cd2892bdd skip en and unchanged 2022-03-24 00:09:55 +08:00
rustdesk
f964827f00 add src/lang/template.rs 2022-03-23 23:58:18 +08:00
rustdesk
16ba58aad3 lang.py for auto translate complete 2022-03-23 23:54:04 +08:00
rustdesk
176045468f Merge branch 'master' of github.com-rustdesk:rustdesk/rustdesk 2022-03-23 12:44:19 +08:00
rustdesk
bb58d7f69a Purslane Ltd. 2022-03-23 12:40:22 +08:00
RustDesk
7824fe1f18 Merge pull request #435 from gengteng/master
use vcpkg to find package
2022-03-22 18:07:42 +08:00
rustdesk
0dd4087408 fix file transfer hanging if disabled, and add trans 2022-03-22 17:09:45 +08:00
gengteng
cc42fee9ea Merge remote-tracking branch 'origin/master'
# Conflicts:
#	libs/scrap/build.rs
2022-03-22 16:34:56 +08:00
gengteng
82f2431eb8 use vcpkg to find package 2022-03-22 16:34:27 +08:00
gengteng
e1c9b607fb use vcpkg to find package 2022-03-22 16:19:01 +08:00
rustdesk
9136b3e3f8 fix style 2022-03-21 14:40:36 +08:00
rustdesk
c03c49d482 bug 2022-03-21 00:53:35 +08:00
rustdesk
3cba56c809 fix id_pk 2022-03-20 21:30:04 +08:00
rustdesk
1e0a347893 refactor signed_pk 2022-03-20 20:20:32 +08:00
RustDesk
7c5d260738 Add files via upload 2022-03-18 15:09:33 +08:00
RustDesk
b31eea0279 Merge pull request #432 from fufesou/virtual_display
Virtual display
2022-03-17 21:05:51 +08:00
fufesou
561a0d20ed virtual display: win10 auto install and uninstall virtual display
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-03-17 20:43:27 +08:00
fufesou
117bbb3409 virtual display: plugout monitor on disconnecting, debug failed, may crash...
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-03-17 20:43:27 +08:00
fufesou
974c259a3d virtual display: win10 trivial refactor
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-03-17 20:43:27 +08:00
fufesou
957eabcef0 virtual display: win10 debug windows.
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-03-17 20:43:27 +08:00
fufesou
1eb696356e virtual display: idd add uninstall && example1
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-03-17 20:43:27 +08:00
fufesou
b734e8aee9 add virtual display
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-03-17 20:43:26 +08:00
fufesou
e6bf858ae1 virtual display: compile example ok, not debug yet
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-03-17 20:42:11 +08:00
rustdesk
b350fbdb9c stupid bug 2022-03-15 12:17:07 +08:00
rustdesk
eaeceeac29 https://github.com/rustdesk/rustdesk/issues/406#issuecomment-1064011977 2022-03-15 12:13:46 +08:00
rustdesk
3f57604891 missed port forward check 2022-03-12 12:38:41 +08:00
rustdesk
565e81d329 fix linux lock screen 2022-03-11 12:41:19 +08:00
rustdesk
362aa9a8ff fix show_progress 2022-03-09 21:43:50 +08:00
rustdesk
4f0a58a691 disable privacy mode (not work well), and disable block input if sas not
enabled (not installed version)
2022-03-09 10:55:13 +08:00
rustdesk
88ac9e9d11 more pynput startup try 2022-03-08 17:59:26 +08:00
rustdesk
ffb0fa4349 pynput run as user 2022-03-08 15:42:58 +08:00
rustdesk
6c5b7b3b89 update rdev 2022-03-08 12:14:52 +08:00
rustdesk
74c3f1d7cc linux AltGr ok 2022-03-08 12:08:18 +08:00
rustdesk
617f87a797 fix wrong format of mac 2022-03-08 01:07:59 +08:00
rustdesk
c632b0e8fb scale cursor 2022-03-08 00:27:12 +08:00
rustdesk
dfd128c817 refactor blank thread exit 2022-03-07 22:26:34 +08:00
rustdesk
71fb27fe4b AltGr works on >10, but not on win7, even with pynput 2022-03-07 20:52:12 +08:00
rustdesk
dcad90e073 more on AltGr 2022-03-07 20:16:28 +08:00
rustdesk
b8f7e347c3 fixing AltGr 2022-03-07 16:19:10 +08:00
rustdesk
ab1805281f basically work, but AltGr not handle well, because confused with Alt_R,
and no idea how to get AltGr state. And on Windows, AltGr (some
keyboard, like br) trigger two key down: Left Control and Alt, how to
handle?
2022-03-07 00:48:20 +08:00
rustdesk
1758aa0f1e try out pynput 2022-03-06 03:10:16 +08:00
rustdesk
bcda7d3193 refactor fix_key_down_timeout 2022-03-05 15:16:10 +08:00
rustdesk
3a7647f48b rdev update for https://github.com/rustdesk/rustdesk/issues/406#issuecomment-1058447377 2022-03-04 13:08:51 +08:00
rustdesk
bf0270323c fix show_progress 2022-03-04 00:52:59 +08:00
rustdesk
488b2455b7 another possible cpu burning 2022-03-03 20:46:27 +08:00
rustdesk
db6f46f165 fix cpu burning issue 2022-03-03 20:25:23 +08:00
rustdesk
c4491b0248 https://github.com/rustdesk/rustdesk/issues/421 2022-03-01 11:19:13 +08:00
rustdesk
cd7b7cc555 fix audio exit bug 2022-03-01 10:38:31 +08:00
RustDesk
e2eef09373 Merge pull request #420 from fy2462/fix_audio_sample_exit_when_mute
Fix audio sample exit when mute
2022-03-01 10:36:18 +08:00
yanfeng
ce46fe7d80 Fix audio sample exit when mute 2022-03-01 10:28:53 +08:00
rustdesk
064879d9d2 revert back because big noise on mac 2022-02-28 18:35:40 +08:00
rustdesk
8648c70df4 refactor 2022-02-28 12:36:32 +08:00
RustDesk
9cc3cf92ab Merge pull request #419 from fy2462/fix_audio_switch_on_linux
Fix audio switch on linux
2022-02-28 12:08:44 +08:00
yanfeng
b19d3f5a1c rename function. 2022-02-28 12:03:24 +08:00
yanfeng
2bcc08f084 Miss the checking code. 2022-02-28 12:00:51 +08:00
yanfeng
aa5c7cc38e Fix switch audio input device failed in index page on Linux. 2022-02-28 11:45:02 +08:00
open-trade
8460c1ac42 format 2022-02-24 14:40:33 +08:00
RustDesk
944fde15a4 Merge pull request #417 from fufesou/copy_paste
remove remote conn id
2022-02-24 11:48:27 +08:00
fufesou
5a07701b90 remove remote conn id
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-02-24 11:32:14 +08:00
rustdesk
8770552448 refactor cm for clipboardfile 2022-02-24 10:38:17 +08:00
RustDesk
4fb8de9b68 Merge pull request #416 from fufesou/copy_paste
Move clipboard service to cm module
2022-02-24 08:51:34 +08:00
fufesou
01591d1abf fix hang up
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-02-24 02:46:47 +08:00
fufesou
128a4aca69 fix crash on windows clipboard
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-02-24 00:26:19 +08:00
fufesou
555ff0085a empty clipboard, debug crash & failed to copy
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-02-24 00:26:19 +08:00
fufesou
2f6b457b3f better control of clipboard file transfer
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-02-24 00:26:19 +08:00
fufesou
8834251eec move clipboard file service to cm module
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-02-24 00:26:19 +08:00
RustDesk
69769cc123 Merge pull request #413 from Heap-Hop/master
try to fix audio play noise;improve audio performance
2022-02-22 20:52:36 +08:00
csf
82d5924401 try to fix audio play noise;improve audio performance 2022-02-22 20:45:49 +08:00
rustdesk
4a03c60ac1 Merge branch 'master' of github.com-rustdesk:rustdesk/rustdesk 2022-02-21 09:39:21 +08:00
rustdesk
f11ca64eac handling IME 2022-02-21 09:39:01 +08:00
RustDesk
9f238bd7ff Merge pull request #410 from victorbnl/master
Fix esperanto README
2022-02-21 08:03:52 +08:00
Victor B
0ce67973f6 Fix esperanto README 2022-02-20 18:58:02 +01:00
rustdesk
6fa8138568 fix CI 2022-02-20 10:12:28 +08:00
RustDesk
270c927d2f Merge pull request #408 from victorbnl/fix-french
Fix french translation
2022-02-20 10:06:29 +08:00
RustDesk
c117eaee2e Merge pull request #407 from victorbnl/esperanto
Add esperanto translation
2022-02-20 10:05:32 +08:00
Victor B
a4fcb8d7c1 Fix french README 2022-02-19 20:18:37 +01:00
Victor B
100daf4031 Fix french translation 2022-02-19 20:14:41 +01:00
Victor B
3b3958ed20 Add esperanto translation 2022-02-19 20:01:28 +01:00
rustdesk
4e9a96dad9 direct access port editable 2022-02-19 15:30:09 +08:00
rustdesk
1c7f9b6f45 https://github.com/rustdesk/rustdesk/issues/264 2022-02-18 11:15:40 +08:00
RustDesk
2786fc97e9 Merge pull request #405 from WoozyMasta/russian
Added localization into Russian
2022-02-17 08:56:55 +08:00
RustDesk
d7becdfa9f Merge branch 'master' into russian 2022-02-17 08:56:47 +08:00
RustDesk
df4ecf9339 Merge pull request #404 from WoozyMasta/fix_de
Fixed loading of German language file
2022-02-17 08:55:57 +08:00
WoozyMasta
a4ba033284 docs: translate community servers table 2022-02-17 02:27:29 +03:00
WoozyMasta
57722c950a fix: load German language 2022-02-17 02:08:18 +03:00
WoozyMasta
691b85b3fc feat: added Russian l18n 2022-02-17 02:05:24 +03:00
rustdesk
c7191023cb test_nat_type sleep time 2022-02-16 20:12:33 +08:00
RustDesk
3aa111b16c Merge pull request #403 from MarcelKuesters/master
Update README-DE.md
2022-02-16 19:37:59 +08:00
Marcel Küsters
2b64375ab0 Update README-DE.md
Did some grammar corrections for German with LanguageTool.org.
2022-02-16 12:24:59 +01:00
RustDesk
b7c1222ce1 Merge pull request #402 from rizlas/master
README translation
2022-02-16 18:57:23 +08:00
rizlas
3dbd62f867 Removed linked README-RU. 2022-02-16 11:53:39 +01:00
rizlas
78be555931 Update header of the other translation 2022-02-16 11:46:57 +01:00
rizlas
c31830f7c4 Update README-IT.md 2022-02-16 11:31:02 +01:00
rizlas
ed0c234b03 Italian translation. Main readme update 2022-02-16 11:27:36 +01:00
rustdesk
52919fd77b remove CLIPRDR_NAME 2022-02-15 22:33:44 +08:00
rustdesk
104c022b26 check_clipboard_file_context later 2022-02-15 22:20:28 +08:00
RustDesk
9b22ee765d Merge pull request #401 from fufesou/copy_paste_3
Windows clipboard -- fix memory leak
2022-02-15 21:33:06 +08:00
fufesou
e80869af67 fix memory leak
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-02-15 21:28:41 +08:00
rustdesk
0b182b9acd more trans 2022-02-15 19:08:29 +08:00
RustDesk
1ca94d7f81 Merge pull request #400 from MarcelKuesters/master
Added German translation.
2022-02-15 18:58:39 +08:00
Marcel Küsters
b0e6a59ded Update lang.rs
Added German language.

Regards.
Marcel Küsters
2022-02-15 11:52:00 +01:00
Marcel Küsters
2f4d02c2bf Create de.rs
Added German translation.

Regards.
Marcel Küsters
2022-02-15 11:42:08 +01:00
rustdesk
835db29c3f fix cliprdr for windows after refactory 2022-02-15 15:35:19 +08:00
rustdesk
933969d1fe refactor cliprdr, not tested on windows yet 2022-02-15 14:46:08 +08:00
RustDesk
e407ba3a33 Merge pull request #399 from fufesou/copy_paste_2
windows clipboard
2022-02-15 13:14:35 +08:00
fufesou
6672087f7c windows clipboard
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-02-15 11:18:53 +08:00
RustDesk
8bb4183098 Update CONTRIBUTING.md 2022-02-14 09:52:43 +08:00
RustDesk
db2b912b3e Merge pull request #397 from FahimFBA/fba
added the Code of Conduct
2022-02-14 09:52:00 +08:00
FahimFBA
fc159fa1f1 added the Code of Conduct 2022-02-14 01:42:34 +06:00
rustdesk
d87f29c679 traditional chinese 2022-02-12 11:50:39 +08:00
RustDesk
a4d34aacea Merge pull request #392 from SiderealArt/patch-1
Add Traditional Chinese translation
2022-02-12 11:44:31 +08:00
SiderealArt
e92700f3f9 Add Traditional Chinese translation 2022-02-12 11:42:39 +08:00
open-trade
8ce94e04b6 fix block_input hanging issue 2022-02-11 14:39:41 +08:00
open-trade
3c29b8a58a fix style 2022-02-10 16:08:50 +08:00
rustdesk
08fdeb7d4b remove old back-compatibility code 2022-02-10 11:32:16 +08:00
rustdesk
4df09f4aec fix style 2022-02-09 20:35:50 +08:00
open-trade
4945605009 fix on cm (connectin not closed somehow) and refactor isEnterKey 2022-02-09 16:06:44 +08:00
open-trade
d313fa92e1 fix clipboard initial sync issue introduced in the PR 2022-02-08 20:34:10 +08:00
open-trade
aa1c0df08f typo 2022-02-08 18:10:32 +08:00
open-trade
dddbae4eb1 fix on should_exit 2022-02-08 18:09:45 +08:00
open-trade
6143a3c649 fix style 2022-02-08 13:58:42 +08:00
open-trade
6c05f72d90 refactor should_exit 2022-02-07 18:39:49 +08:00
rustdesk
809c220eaf stupid workaround for https://sciter.com/forums/topic/crash-on-latest-tis-mac-sdk-sometimes/ 2022-02-06 18:19:06 +08:00
rustdesk
3ec69b6d97 refactor video_ack_required 2022-02-05 01:19:24 +08:00
rustdesk
5a0f8d008e video_ack_required for web 2022-02-04 22:18:48 +08:00
rustdesk
eb49af843c tmp solution for msgbox in scrollable 2022-02-04 11:20:01 +08:00
rustdesk
9c6715f95e reset input_blocked after reconnection 2022-02-01 23:43:42 +08:00
rustdesk
39ea73657d typo 2022-02-01 21:52:07 +08:00
rustdesk
7d14ce98e1 fix style 2022-02-01 18:33:18 +08:00
rustdesk
3112792b7b fix new msgbox when wrong password 2022-02-01 16:32:56 +08:00
rustdesk
cd62d7024b new msgbox 2022-02-01 02:38:52 +08:00
rustdesk
bc3d3bd0ec refactor server keyboard/clipboard enabled 2022-01-31 18:00:57 +08:00
rustdesk
484f50811d no privacy mode if keyboard disabled 2022-01-31 17:27:21 +08:00
rustdesk
2a11bc63ce more trans and format 2022-01-31 01:54:49 +08:00
rustdesk
64071943fc change to async channel 2022-01-30 21:37:46 +08:00
rustdesk
29ca2ed14d format 2022-01-30 21:34:34 +08:00
rustdesk
e23a6805e3 move audio/video decoder in seperate thread 2022-01-30 21:16:08 +08:00
rustdesk
5a9803c2c8 format lang 2022-01-30 03:41:18 +08:00
rustdesk
b5f056c0c0 missed options init 2022-01-29 21:30:14 +08:00
rustdesk
495cc9056e Merge branch 'master' of github.com-rustdesk:rustdesk/rustdesk 2022-01-29 16:56:39 +08:00
rustdesk
6a19b8caa1 refactor msgbox 2022-01-29 16:56:24 +08:00
open-trade
2719936ea9 change tab padding to 8 2022-01-28 17:55:09 +08:00
open-trade
4108635b34 refactor tab responsive size again 2022-01-28 17:48:49 +08:00
open-trade
9118511bbd min 3 chars 2022-01-28 17:13:56 +08:00
open-trade
7b06dab4ee improve responsive tab size 2022-01-28 16:58:32 +08:00
open-trade
ea2fe3eff0 https://github.com/rustdesk/rustdesk/issues/366 2022-01-24 15:51:29 +08:00
rustdesk
1cda704628 more test_nat_type 2022-01-24 03:15:01 +08:00
rustdesk
a3511d9157 update crates, and set new default #cpu 2022-01-24 02:26:07 +08:00
rustdesk
98aa410683 more set_nodelay 2022-01-24 01:50:22 +08:00
rustdesk
bf578e768b set_nodelay 2022-01-23 20:53:55 +08:00
open-trade
372b715162 bug fix on file transfer window 2022-01-21 15:13:29 +08:00
rustdesk
b0ddd3d543 fix on file type (after protobuf change), improve current row select,
still has bug for detecting file type under Windows
2022-01-21 12:52:08 +08:00
rustdesk
a474f904b1 for back compatibility 2022-01-21 02:06:33 +08:00
rustdesk
cd9faf48f3 new pk 2022-01-20 12:48:55 +08:00
rustdesk
b76a1d36cb typo 2022-01-20 00:25:01 +08:00
rustdesk
893d8b39c9 fix style on linux 2022-01-19 23:30:21 +08:00
open-trade
326eed5ee0 make tcp sync 2022-01-19 16:40:05 +08:00
rustdesk
a1b9e1b229 https://github.com/rustdesk/rustdesk/issues/356 2022-01-19 11:18:12 +08:00
rustdesk
4b51fffc96 update rdev for kp8/9 bug on mac 2022-01-18 12:24:07 +08:00
rustdesk
3485d2ddc7 fix css style 2022-01-17 20:50:48 +08:00
open-trade
92a1bb04e9 make proto compatible to c++ 2022-01-17 16:53:17 +08:00
open-trade
02cbc0d407 fix style 2022-01-17 15:05:33 +08:00
rustdesk
e0637f966a sync config if enable mac service 2022-01-17 12:38:44 +08:00
rustdesk
5af1258454 refactor mac service 2022-01-17 12:05:06 +08:00
rustdesk
a12f24bf16 remove InputFunc 2022-01-15 22:03:17 +08:00
rustdesk
9651666d41 code refactory 2022-01-15 21:33:20 +08:00
rustdesk
6bd730bc67 unwrap -> ok to avoid unintended crash 2022-01-15 19:11:19 +08:00
rustdesk
35816d4fbb polish block input 2022-01-15 18:27:15 +08:00
RustDesk
647721a37e Merge pull request #373 from fufesou/privacy_mode
Privacy mode
2022-01-15 17:22:11 +08:00
fufesou
25492c815c simple privacy mode
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-01-15 16:57:07 +08:00
fufesou
a1c4b08535 simple privacy demo
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-01-15 16:32:55 +08:00
rustdesk
8f998771c9 refactor process id 2022-01-15 14:08:24 +08:00
rustdesk
f47dcd1a8b remove psutil which is too old 2022-01-15 13:47:57 +08:00
rustdesk
d069b73303 refactor 2022-01-15 02:16:00 +08:00
RustDesk
6fe4344cb0 Merge pull request #370 from Heasn/master
Fix some macOS new services issues
2022-01-14 23:22:08 +08:00
rustdesk
4fe5d2cf02 no lan discovery if no install 2022-01-14 23:21:30 +08:00
rustdesk
95239fc148 change back to broadcast, because multicast has big problem if multiple
interface with 0.0.0.0 binding
2022-01-14 23:02:08 +08:00
Chen Baiyu
5fb613d4b2 Merge branch 'rustdesk:master' into master 2022-01-14 18:31:18 +08:00
chenbaiyu
c8df8ae551 collapse imports 2022-01-14 18:30:34 +08:00
chenbaiyu
d0ca9de946 add new service install tip in Chinese 2022-01-14 18:28:39 +08:00
open-trade
0a2bc1cf8a try out muliticast on multiple interface 2022-01-14 18:16:00 +08:00
chenbaiyu
d5286782cd fix server service not start after daemon installed at first time 2022-01-14 17:36:41 +08:00
RustDesk
07aa0898c5 Merge pull request #369 from Heasn/master
New launch daemon/agents and config sync service on macOS
2022-01-14 10:49:48 +08:00
chenbaiyu
4d37a9ee23 fix CI failed build on linux 2022-01-14 03:52:39 +08:00
chenbaiyu
1fda4c257d fix CI failed build on linux 2022-01-14 03:47:16 +08:00
chenbaiyu
fea4b068cd fix CI failed build on linux 2022-01-14 03:43:01 +08:00
chenbaiyu
e23eb3e79b Merge remote-tracking branch 'origin/master' 2022-01-14 03:38:41 +08:00
chenbaiyu
78450fda08 fix CI failed build on linux 2022-01-14 03:38:22 +08:00
Chen Baiyu
78f2d3f31f Merge branch 'rustdesk:master' into master 2022-01-14 03:18:41 +08:00
chenbaiyu
b4f61c735e fix plist files and enhance privilege escalation method 2022-01-14 03:17:36 +08:00
rustdesk
7944e0bc36 fix CI 2022-01-14 01:29:52 +08:00
rustdesk
780b57f597 load keyboard layout for mac 2022-01-14 01:15:03 +08:00
chenbaiyu
29bb10a40a modify daemon install check 2022-01-13 20:34:28 +08:00
chenbaiyu
8e6dd76c5b remove unused import and launch service when install 2022-01-13 19:42:25 +08:00
chenbaiyu
9be6b17a8b Add launch service 2022-01-13 19:23:41 +08:00
open-trade
7b1806b0f3 disable crc, because super slow on my Ubuntu in virtualbox 2022-01-13 19:00:00 +08:00
chenbaiyu
f45a2c7a94 Add user and root config sync action 2022-01-13 16:33:51 +08:00
Chen Baiyu
81e43c2970 Merge branch 'rustdesk:master' into master 2022-01-13 16:08:57 +08:00
chenbaiyu
e51e5ac4b1 Revert "temp commit"
This reverts commit 2e03ca19f6.
2022-01-13 16:07:18 +08:00
chenbaiyu
1995f9fa4e Revert "temp commit"
This reverts commit 88f0f67ee3.
2022-01-13 16:06:51 +08:00
chenbaiyu
88f0f67ee3 temp commit 2022-01-13 15:26:57 +08:00
rustdesk
d379f23490 my bad 2022-01-13 02:11:47 +08:00
rustdesk
75ef279e47 avoid select! all branches disabled panic 2022-01-13 01:16:23 +08:00
chenbaiyu
5b03e99404 Merge remote-tracking branch 'origin/master' 2022-01-12 21:40:19 +08:00
chenbaiyu
2e03ca19f6 temp commit 2022-01-12 21:40:02 +08:00
open-trade
3aebc43111 more control keys, and VkKeyScanW -> VkKeyScanExW with forground window
keyboard layout
2022-01-12 18:11:42 +08:00
rustdesk
8ea5d80f01 new lan discovery https://github.com/rustdesk/rustdesk/issues/261 2022-01-12 03:10:15 +08:00
open-trade
4071f803f7 fix compile error 2022-01-11 16:59:53 +08:00
open-trade
65eef2b579 raw lan discovery 2022-01-11 16:24:35 +08:00
open-trade
9c9855877d bind_multicast 2022-01-10 18:58:51 +08:00
open-trade
9a92b6ac4a revert back from lan discovery merge 2022-01-10 18:05:42 +08:00
RustDesk
b400e4305f Merge pull request #337 from fufesou/lan_discovery
Lan discovery
2022-01-10 17:35:54 +08:00
RustDesk
dfeb9a29c1 Merge branch 'master' into lan_discovery 2022-01-10 17:34:51 +08:00
rustdesk
e2a879692d ignore modifiers for name 2022-01-10 03:11:53 +08:00
rustdesk
3a6dc19616 to be compatible with 1.1.8 2022-01-10 01:29:50 +08:00
rustdesk
ae79a36f7b remove valid_for_capslock 2022-01-10 01:06:31 +08:00
rustdesk
3212290f6e fix on rdev 2022-01-10 00:33:31 +08:00
rustdesk
d07ae9f2c6 numpad 2022-01-09 23:59:30 +08:00
rustdesk
3f56c82c7b revert keysym back, enigo's Layout can do this 2022-01-09 21:05:00 +08:00
rustdesk
a0c704f36e string len is num of bytes 2022-01-09 20:56:56 +08:00
rustdesk
baccff8f99 Merge branch 'master' of github.com-rustdesk:rustdesk/rustdesk 2022-01-09 19:56:48 +08:00
rustdesk
0a294d9ff3 https://github.com/rustdesk/rustdesk/issues/292 2022-01-09 19:56:24 +08:00
RustDesk
03fb47b312 Merge pull request #361 from Heasn/master
fix pre-login window behavior on macOS Big Sur or above
2022-01-08 02:17:28 +08:00
chenbaiyu
29f15aabed fix security problem caused server hang and unexpected input behavior at pre-login window when macOS version on Big Sur or above 2022-01-08 01:39:54 +08:00
RustDesk
089acaa6e7 Merge pull request #359 from fufesou/master
Failed to decode audio frame
2022-01-07 21:34:53 +08:00
fufesou
709a2a30bc Merge branch 'rustdesk:master' into master 2022-01-07 21:30:51 +08:00
fufesou
54269b6f5d fix audio play with sample rate 48000
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-01-07 21:30:13 +08:00
open-trade
a7a4cd7eac CI 2022-01-07 18:05:33 +08:00
open-trade
26d161f827 working on keysym 2022-01-07 18:03:55 +08:00
open-trade
9df1fcb783 update tigervnc 2022-01-07 16:21:56 +08:00
open-trade
e82f040d6d kick start international keyboard 2022-01-07 13:59:21 +08:00
rustdesk
1931cb8c7c https://github.com/rustdesk/rustdesk/issues/356 2022-01-05 23:50:13 +08:00
rustdesk
32c5437c5d more equal check in config 2022-01-05 21:12:07 +08:00
open-trade
1b61b77fbe more trans 2022-01-05 18:38:40 +08:00
open-trade
c0b6367137 sock5 gui part 2022-01-05 18:34:30 +08:00
open-trade
12ab22e048 bug fix 2022-01-05 17:10:12 +08:00
open-trade
7bde8a3713 remove some unnessary handler.msgbox 2022-01-05 16:53:37 +08:00
open-trade
9c55e1efc8 fix on msgbox 2022-01-05 16:48:09 +08:00
open-trade
b24e16d6c1 bug fix for msgbox, todo: test more for msgbox in file_transfer.tis 2022-01-05 16:32:45 +08:00
open-trade
6767dda246 refactor 2022-01-05 15:59:01 +08:00
open-trade
5f61c2442a bug fix 2022-01-05 15:47:04 +08:00
open-trade
5631ffac4c fix 2022-01-05 15:09:36 +08:00
open-trade
78097f4006 refactort 2022-01-05 14:38:38 +08:00
rustdesk
1d8cdb5e93 refactor target address 2022-01-05 13:21:14 +08:00
open-trade
3e590b8212 refactor to_socket_addr and dns_check 2022-01-04 19:49:44 +08:00
open-trade
533efd04d7 rename 2022-01-04 17:45:52 +08:00
open-trade
fb392b81cb rendezvous_mediator: ensure once one exits, the others also exit. 2022-01-04 17:44:06 +08:00
rustdesk
cbcad03bc6 fix style 2022-01-04 11:22:09 +08:00
RustDesk
2ec5f8fe7e Merge pull request #353 from fufesou/socks5
Socks5
2022-01-04 01:11:04 +08:00
fufesou
875570e040 refactor udp framed
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-01-04 00:44:50 +08:00
fufesou
6d506cbb64 socks5 support
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2022-01-03 22:50:43 +08:00
open-trade
b17bda9a55 resize tab 2022-01-03 16:31:13 +08:00
rustdesk
d6b56a2f35 refactor 2022-01-03 11:16:07 +08:00
rustdesk
64f181e4a1 fav 2022-01-03 00:24:36 +08:00
rustdesk
1552402907 working on fav 2022-01-02 21:56:04 +08:00
rustdesk
f0a6c706fa https://github.com/rustdesk/rustdesk/issues/275 2022-01-02 15:09:44 +08:00
rustdesk
042114ae37 refactor 2022-01-02 14:23:32 +08:00
rustdesk
241623c406 reload session list if alias change 2022-01-02 13:56:47 +08:00
rustdesk
40730cbbae ID search 2022-01-02 11:40:30 +08:00
rustdesk
cedc384ba1 working on search bar 2022-01-01 19:44:02 +08:00
rustdesk
15f3c36c5f header button hover bg 2022-01-01 17:18:10 +08:00
rustdesk
ee088a8ddf workaround for stupid sciter 2021-12-31 18:38:46 +08:00
open-trade
cb1818ab37 same width of session card 2021-12-30 16:31:33 +08:00
rustdesk
66af938858 https://sciter.com/forums/topic/menu-not-be-hidden-when-open-dialog-on-linux/ 2021-12-29 23:40:24 +08:00
open-trade
e26a838882 fix on log after upgrade 2021-12-29 19:01:36 +08:00
open-trade
e0bb25cbe5 upgrade vcpkg 2021-12-29 19:00:29 +08:00
open-trade
3491c79cbc get_local_option for ui style, todo: set_local_option 2021-12-29 17:53:36 +08:00
rustdesk
365fc90d8b refactor msgbox 2021-12-29 11:42:43 +08:00
rustdesk
8be7331cb6 add it 2021-12-29 00:48:58 +08:00
RustDesk
ea46d2493e Merge pull request #347 from ale-rinaldi/feature/italian-translation
Italian translation
2021-12-29 00:46:57 +08:00
Alessandro Rinaldi
1141be01f5 Italian translation 2021-12-28 17:42:50 +01:00
rustdesk
6c713f3135 reset AUDIO_ZERO_COUNT 2021-12-29 00:20:51 +08:00
RustDesk
3059ca061e Merge pull request #346 from Heap-Hop/master
optimize audio
2021-12-29 00:11:41 +08:00
rustdesk
2631c68b88 fix cm minimized not working sometimes 2021-12-29 00:05:52 +08:00
csf
f69f6bc8d4 optimize audio 2021-12-29 00:00:23 +08:00
open-trade
66e39b62a2 https://github.com/rustdesk/rustdesk/issues/223 2021-12-28 18:33:36 +08:00
RustDesk
993a419793 Merge pull request #344 from liyue201/dev
fix dependence
2021-12-28 14:27:22 +08:00
liyue
f1444049bf fix dependence 2021-12-28 14:18:37 +08:00
rustdesk
da629ec42c remove unused 2021-12-27 02:38:22 +08:00
rustdesk
7225c1fcf0 session list style and refactor 2021-12-27 02:28:25 +08:00
rustdesk
dbdff120bc move get_version_number to hbb_common 2021-12-27 00:24:57 +08:00
rustdesk
51f4f736bc update package 2021-12-26 15:34:10 +08:00
rustdesk
d4d90da196 https://github.com/rustdesk/rustdesk/issues/301 2021-12-25 22:31:42 +08:00
RustDesk
9903e9df9e Update README.md 2021-12-25 16:55:01 +08:00
rustdesk
af218dbc83 internationalization 2021-12-25 16:45:22 +08:00
rustdesk
b3e3f6151d get last env instead of the first one avoid problem when just switch from wayland to xorg 2021-12-25 01:07:41 +08:00
rustdesk
3d39d9c27c https://github.com/rustdesk/rustdesk/issues/328 2021-12-25 00:18:54 +08:00
rustdesk
589177fc94 Merge branch 'master' of github.com-rustdesk:rustdesk/rustdesk 2021-12-24 19:13:38 +08:00
rustdesk
4703a7d332 https://github.com/rustdesk/rustdesk/issues/327 2021-12-24 19:13:11 +08:00
rustdesk
8d90c5a93b change codec cpu usage to 0 2021-12-24 12:40:47 +08:00
rustdesk
885d8a4586 https://github.com/rustdesk/rustdesk/issues/332 2021-12-24 00:27:27 +08:00
rustdesk
0e8fc4a815 65515 -> Meta(win) on Linux 2021-12-23 23:03:43 +08:00
rustdesk
96afb88518 change line-through style from grey to red 2021-12-23 21:41:53 +08:00
open-trade
a30aaebc72 fix clipboard crash and https://github.com/rustdesk/rustdesk/issues/302 2021-12-23 17:44:44 +08:00
rustdesk
252d3cb797 refactor 2021-12-23 11:11:48 +08:00
open-trade
26a4b1f3eb comment on bias 2021-12-22 16:51:33 +08:00
open-trade
dc724a30e7 https://github.com/rustdesk/rustdesk/issues/298 2021-12-22 14:56:10 +08:00
open-trade
334c94ceb3 https://github.com/rustdesk/rustdesk/issues/210 2021-12-22 14:28:08 +08:00
RustDesk
b6feaa695f Merge pull request #338 from Heap-Hop/master
adjust #[warn(unreachable_code)] position
2021-12-21 17:45:54 +08:00
csf
5f190297a9 adjust #[warn(unreachable_code)] position 2021-12-21 16:35:18 +08:00
fufesou
35462eecfe comment out discovery button
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2021-12-21 01:17:29 +08:00
fufesou
d00352f4e4 lan discovery almost done
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2021-12-21 00:34:10 +08:00
fufesou
5682b088de lan discovery will be done soon
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2021-12-21 00:34:10 +08:00
fufesou
bcbe9ccbe5 trivial changes
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2021-12-21 00:34:09 +08:00
fufesou
87f50a6318 lan discovery in socket_cs
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2021-12-21 00:34:09 +08:00
rustdesk
362b5594a2 nothing big 2021-12-21 00:11:12 +08:00
RustDesk
b9d8de1ec1 Merge pull request #335 from fufesou/fix_video_image_tearing
Fix video image tearing
2021-12-20 23:15:07 +08:00
fufesou
8a6b33b841 image tearing fixed
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2021-12-20 22:21:15 +08:00
fufesou
3ffd8ac146 add video channel
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2021-12-20 17:19:56 +08:00
RustDesk
07ea52d620 Merge pull request #331 from fufesou/master
add error log for graphics failure
2021-12-20 13:26:56 +08:00
fufesou
4cb967251b add error log for graphics failure
Signed-off-by: fufesou <shuanglongchen@yeah.net>
2021-12-10 22:36:34 +08:00
rustdesk
29905608b5 fix on NL 2021-12-10 00:46:23 +08:00
RustDesk
36db9f65cd Merge pull request #326 from jeroenhd/master
Add Dutch translation for README
2021-12-10 00:12:16 +08:00
jeroenhd
91445da094 Add hyperlinks to Dutch translation
Signed-off-by: jeroenhd <git@jeroenhd.nl>
2021-12-08 02:34:13 +01:00
jeroenhd
083d6c591a Add Dutch translation of the README
Signed-off-by: jeroenhd <git@jeroenhd.nl>
2021-12-08 02:29:55 +01:00
RustDesk
e352ea67f4 Merge pull request #320 from ioridev/master
README translated to Japanese (README-JP.md)
2021-12-01 18:16:56 +08:00
iori
4103ab70a7 Update README-JP 2021-12-01 17:11:06 +09:00
iori
fd9d6db2ed Create README-JP.md 2021-12-01 17:08:10 +09:00
RustDesk
d0b15fbd2a Merge pull request #316 from josephjosedev/master
Update README-ML.md
2021-11-27 13:19:48 +08:00
Joseph Jose
7c42c04b23 Update README-ML.md
updated
2021-11-27 10:42:38 +05:30
Joseph Jose
81e4998a37 Update README-ML.md 2021-11-26 22:50:40 +05:30
RustDesk
1ab5bb0a2e Update README.md 2021-11-27 01:05:29 +08:00
RustDesk
0f39626782 Merge pull request #315 from varghesejose2020/master
README translated to MALAYALAM (README-ML.md)
2021-11-27 01:00:58 +08:00
Varghese Jose
dc2edcec5d Update README-ML.md 2021-11-26 13:55:56 +05:30
Varghese Jose
3198236a8c Update README-ML.md
updated
2021-11-26 13:54:53 +05:30
Varghese Jose
e044212eb6 Update README-ML.md
updated
2021-11-26 13:50:20 +05:30
Varghese Jose
33e8f2aa85 Update README-ML.md
upd
2021-11-26 13:45:44 +05:30
Varghese Jose
031ca4e50c Update README-ML.md 2021-11-26 13:40:30 +05:30
Varghese Jose
73d0da726d Update README-ML.md 2021-11-26 13:38:28 +05:30
Varghese Jose
5c97f5dce5 Create README-ML.md
MALAYALAM added to README
2021-11-26 13:22:44 +05:30
RustDesk
8d5aa731a1 Merge pull request #306 from mingxingren/master
Delete a line of typos
2021-11-23 20:28:49 +08:00
mamingkun
e8c5a63986 1. Delete a line of duplicate code 2021-11-23 20:07:25 +08:00
mingxingren
46fe37015f Merge pull request #1 from rustdesk/master
Update from master
2021-11-23 20:06:07 +08:00
rustdesk
b79f086df5 suomi -> Suomi 2021-11-22 01:42:53 +08:00
rustdesk
6afb6aaff2 Fix on FI 2021-11-22 01:40:45 +08:00
rustdesk
5a1ab37171 FI 2021-11-22 01:38:58 +08:00
RustDesk
5e0bf8f5a9 Merge pull request #304 from fufesou/master
resolution changed, no need to reconnect
2021-11-21 23:10:00 +08:00
cxl
7964afeb84 resolution changed, no need to reconnect
Signed-off-by: cxl <xiaolong.chen@nazhiai.com>
2021-11-21 22:45:12 +08:00
RustDesk
3759347d47 Merge pull request #294 from hatamiarash7/master
Spell & Format
2021-11-15 00:12:59 +08:00
Arash Hatami
2758f6b7d5 Fix misspelled words 2021-11-14 19:01:34 +03:30
Arash Hatami
70a4ee4318 Merge branch 'rustdesk:master' into master 2021-11-14 18:52:51 +03:30
Arash Hatami
7f13edd14a Fix misspelled words 2021-11-14 18:52:05 +03:30
Arash Hatami
96208e9fef git ignore .vscode 2021-11-14 18:36:03 +03:30
rustdesk
e6bd5b0698 pb in version 2021-11-07 10:18:10 +08:00
rustdesk
231231e51f refactor 2021-10-30 14:03:33 +08:00
RustDesk
247ea5fed3 Merge pull request #279 from cc-morning/master
Clipboard service optimization and bug fixes
2021-10-30 12:50:39 +08:00
cc-morning
0cf2db9239 Clipboard listener lifecycle follows service 2021-10-27 20:02:17 +08:00
cc-morning
318e3cbd7d Code Format 2021-10-26 16:59:31 +08:00
cc-morning
5164f76919 Fix lost clipboard content again 2021-10-25 16:25:23 +08:00
cc-morning
972ec8d79d Fix missing clipboard content 2021-10-24 23:47:02 +08:00
RustDesk
516904551c Merge pull request #268 from cc-morning/master
Optimize clipboard change listener
2021-10-24 00:45:52 +08:00
cc-morning
1bf80e3dd6 Optimize clipboard change listener 2021-10-22 16:02:01 +08:00
RustDesk
8f22273759 Update ci.yml 2021-10-21 10:00:53 +08:00
rustdesk
1ddd5203e5 fix overflow 2021-10-20 17:03:48 +08:00
RustDesk
62d2c0fb6d Merge pull request #265 from dannkunt/master
Fix buiding trough docker
2021-10-20 14:24:44 +08:00
dannkunt
0db250f02a Delete this code
This code is unnessesary and bug casing with previous fix
2021-10-20 08:38:36 +03:00
dannkunt
8be912a8cf Add user privelege
To fix this
2021-10-20 08:35:52 +03:00
RustDesk
03f913e49d Merge pull request #256 from starccy/multiple-selection
Transfer multiple files
2021-10-19 23:36:15 +08:00
Starccy
fb126164ef use multiple jobs to delete 2021-10-19 21:52:59 +08:00
Starccy
eea85b9b5a send & receive multiple files 2021-10-17 21:27:10 +08:00
RustDesk
b16b2bc1b4 Merge pull request #253 from palfrey/ci
CI setup
2021-10-12 23:47:09 +08:00
Tom Parker-Shemilt
55d21ab151 Just build the tests 2021-10-11 22:35:31 +01:00
Tom Parker-Shemilt
d25e17317d Skip tests for the moment 2021-10-11 22:09:13 +01:00
Tom Parker-Shemilt
7a7cca7e45 Add rust cache 2021-10-11 21:48:56 +01:00
Tom Parker-Shemilt
0ef4246360 Set vcpkg commit id 2021-10-11 21:40:06 +01:00
Tom Parker-Shemilt
686e495171 Initial CI setup 2021-10-11 21:36:45 +01:00
rustdesk
c0db2e6da4 refactor and fix 2021-10-08 00:16:10 +08:00
rustdesk
c0459b8f94 move change wayland to linux section 2021-10-02 08:51:56 +08:00
rustdesk
678a3d2d28 README format bug 2021-10-02 08:48:41 +08:00
Arash Hatami
2894a5ab7b Format rust files 2021-10-01 22:48:04 +03:30
RustDesk
2efd0e61b4 Merge pull request #243 from hatamiarash7/master
Update Readme & Other Markdown files
2021-10-01 17:05:17 +08:00
Arash Hatami
18b1646cd4 Fix Markdown syntax in all MD files 2021-10-01 12:28:08 +03:30
Arash Hatami
66cdbbacd0 Update README.md
- Remove extra space after `git clone` command
- Add `VCPKG_ROOT` env before `cargo run` command
2021-10-01 12:10:53 +03:30
rustdesk
aaba4c144c fix README 2021-09-30 12:07:18 +08:00
RustDesk
2d5758e880 Update README.md 2021-09-30 12:01:45 +08:00
RustDesk
b20ec86fac Merge pull request #237 from kerlw/master
Add some optimization options for Chinese developer in README-ZH.md.
2021-09-26 10:10:57 +08:00
kerl.d.w
1df5234eea Add some optimization options for Chinese developer in README-ZH.md. 2021-09-26 09:51:40 +08:00
RustDesk
1b8dbbeac9 https://github.com/rustdesk/rustdesk/issues/226 2021-09-12 17:53:45 +08:00
RustDesk
c5f1222476 Merge pull request #224 from desertstsung/addfun/relogin_xorg
add function
2021-09-09 18:24:58 +08:00
desertstsung
1009eabdfe add function
relogin required if current is wayland
2021-09-09 15:07:09 +08:00
open-trade
8138a661a6 new fall back to gdi 2021-09-07 19:03:59 +08:00
RustDesk
d369955790 Merge pull request #221 from desertstsung/ui/labelchange
ui label change
2021-09-06 20:59:12 +08:00
desertstsung
0afca9d1ea ui label change:
src/ui/index.tis#L547:Fix it -> Disable it
2021-09-06 20:41:37 +08:00
rustdesk
0325500ebf refactor 2021-08-29 19:26:33 +08:00
RustDesk
b0dfd777fb Update Cargo.toml 2021-08-24 22:18:39 +08:00
rustdesk
1a54c50c6f fix cpal crash on alsa linu 2021-08-23 13:04:21 +08:00
RustDesk
5d26dbaa90 Merge pull request #202 from open-trade/patch-1
My stupidness
2021-08-20 13:59:21 +08:00
open-trade
c52f4af17d My stupidness 2021-08-20 13:57:53 +08:00
rustdesk
b2a6c592ba linux clipboard sync issue https://github.com/rustdesk/rustdesk/issues/118 2021-08-20 12:39:10 +08:00
rustdesk
2df4da89dc somebody not tidy, but like tidy code, :), https://github.com/rustdesk/rustdesk/issues/198 2021-08-16 21:28:59 +08:00
rustdesk
aaffbe476e fix 32 2021-08-14 01:13:40 +08:00
rustdesk
dae3a2b43b compile error 2021-08-14 01:06:06 +08:00
rustdesk
64b4d14629 fix on 32 2021-08-14 01:02:39 +08:00
rustdesk
d03172e2f3 prepare 32 2021-08-14 00:45:12 +08:00
rustdesk
44f6233df0 tokio 1.10 2021-08-13 13:02:03 +08:00
RustDesk
88a3266a73 Update CONTRIBUTING.md 2021-08-13 01:31:47 +08:00
rustdesk
3cd9ee2aa3 unify menu style 2021-08-12 20:16:57 +08:00
rustdesk
a76916c520 ignore abnormal latency 2021-08-12 10:55:21 +08:00
rustdesk
2102813ed9 refactor 2021-08-12 01:25:32 +08:00
rustdesk
c970e5b22b shared memory for future usage, but it has permission problem on
Windows, not find way to make files writable for all users on Windows
2021-08-11 21:08:05 +08:00
rustdesk
3a7d64bf34 atomic 2021-08-11 18:29:03 +08:00
rustdesk
4e85841398 refactor msgbox retry 2021-08-11 01:28:53 +08:00
rustdesk
6130792734 fix cm style 2021-08-10 23:50:32 +08:00
rustdesk
61caaa3365 refactor, will do with shared memory 2021-08-10 16:01:39 +08:00
rustdesk
c3a3c1a1c7 atexit crash on mac 2021-08-10 12:19:42 +08:00
rustdesk
e510d2744d fix apps key 2021-08-10 12:18:10 +08:00
rustdesk
bb25964307 safe exit 2021-08-09 04:21:42 +08:00
rustdesk
8affa24400 how about fix_modifiers? 2021-08-09 02:07:54 +08:00
rustdesk
ad182a5f3c comment on altgr 2021-08-08 18:23:44 +08:00
rustdesk
6ed9526a65 comment on jp/kr key mapping 2021-08-08 18:06:26 +08:00
rustdesk
ccd1cab6bc down as press only for linux and non-modifier 2021-08-08 17:29:39 +08:00
rustdesk
ab4843b76e fixing win key problem https://github.com/rustdesk/rustdesk/issues/35 2021-08-08 01:44:37 +08:00
rustdesk
3200002e52 fix unexpected repeating key input on remote linux https://github.com/rustdesk/rustdesk/issues/189 2021-08-06 14:23:50 +08:00
rustdesk
9d7dced7e7 .gitattributes 2021-08-05 11:27:56 +08:00
rustdesk
a70e3e93b0 fix remote_cursor https://github.com/rustdesk/rustdesk/issues/82, host
has higher priority to control mouse https://github.com/rustdesk/rustdesk/issues/40
2021-08-04 15:40:34 +08:00
rustdesk
646b11a3ae typo 2021-08-04 15:30:47 +08:00
rustdesk
eb76f7cecc fix mac key mapping, https://github.com/rustdesk/rustdesk/issues/186, https://github.com/rustdesk/rustdesk/issues/86 2021-08-04 03:44:00 +08:00
rustdesk
39f0dd28b4 <video> can not be relative, add another wrapper to make img cursor work 2021-08-04 00:57:48 +08:00
rustdesk
66bd97c0b3 bigger client timeout 2021-08-04 00:57:03 +08:00
rustdesk
a0b2450888 fix on --password 2021-08-03 20:16:38 +08:00
rustdesk
f558c12866 --password https://github.com/rustdesk/rustdesk/issues/187 2021-08-03 14:59:45 +08:00
rustdesk
c385d88708 https://github.com/rustdesk/rustdesk/issues/133 https://github.com/rustdesk/rustdesk/issues/112 https://github.com/rustdesk/rustdesk/issues/43 2021-08-01 14:51:53 +08:00
rustdesk
2e305e8f11 fix on rubato 2021-08-01 11:05:45 +08:00
rustdesk
e949023dda try out the other audio resampler 2021-08-01 11:01:04 +08:00
rustdesk
25c10453e5 password eye padding 2021-07-31 22:25:04 +08:00
rustdesk
935676468b disable systray which has compatibility issue 2021-07-31 03:51:10 +08:00
rustdesk
49dff161dd enable dxgi https://github.com/rustdesk/rustdesk/issues/79, may fix https://github.com/rustdesk/rustdesk/issues/169 2021-07-31 03:00:07 +08:00
rustdesk
7282a462f4 scrap readme 2021-07-29 13:33:26 +08:00
rustdesk
a740870b67 fix on android 2021-07-29 13:30:12 +08:00
rustdesk
cd9c189c64 bigger relay timeout 2021-07-28 19:41:34 +08:00
rustdesk
905a3a2936 fix sciter-rs utf 2021-07-28 00:00:11 +08:00
rustdesk
e6744d031d connection type 2021-07-27 23:53:12 +08:00
rustdesk
a3f5ffc15a fix on linux numpadenter 2021-07-27 20:12:53 +08:00
rustdesk
191fdc6691 fix keyboard abnormal, https://github.com/rustdesk/rustdesk/issues/146 https://github.com/rustdesk/rustdesk/issues/135 https://github.com/rustdesk/rustdesk/issues/127 2021-07-27 20:10:04 +08:00
rustdesk
f07ce11425 https://github.com/rustdesk/rustdesk/issues/130 better toolbar hide/show 2021-07-26 23:40:58 +08:00
rustdesk
7324cb607c wheel issue for new sciter 2021-07-26 21:34:05 +08:00
rustdesk
1ee92c9f68 fix for file transfer: sort row and remove empty dir 2021-07-26 02:50:33 +08:00
rustdesk
9a86a595ff fix compatibility issue for new sciter 2021-07-26 01:50:47 +08:00
rustdesk
879c300563 boundery check, https://github.com/rustdesk/rustdesk/issues/107 2021-07-25 21:04:11 +08:00
rustdesk
bebe136834 less green 2021-07-25 02:09:57 +08:00
rustdesk
d89d5ef825 https://github.com/rustdesk/rustdesk/issues/132#issuecomment-886069737 2021-07-25 02:06:20 +08:00
rustdesk
56dfcffd1e restore Fedora vpx fix 2021-07-24 20:00:56 +08:00
rustdesk
7c5915e3d3 vpxmt -> vpx after vcpkg upgraded 2021-07-24 19:33:11 +08:00
rustdesk
cb2864202f upgrade vcpkg 2021-07-24 19:06:32 +08:00
RustDesk
dae2814951 Update Dockerfile 2021-07-24 18:41:22 +08:00
rustdesk
6922a1de4c refactor and upgrade sciter 2021-07-24 18:25:07 +08:00
RustDesk
7282c3a16d Update README.md 2021-07-23 17:54:16 +08:00
rustdesk
c15c44788c try out wayland 2021-07-23 17:52:38 +08:00
RustDesk
d83163b6a0 Merge pull request #170 from sitiom/nsis-setup
Replace InnoSetup with improved NSIS Setup
2021-07-15 21:48:55 +08:00
Ryan Caezar Itang
5383c09e3d Replace InnoSetup with improved NSIS Setup 2021-07-15 20:51:41 +08:00
RustDesk
6f8483ece6 Add files via upload 2021-07-14 22:23:42 +08:00
RustDesk
e65aa61fb7 Update README-FR.md 2021-07-08 22:57:07 +08:00
rustdesk
2522c99f47 update readme 2021-07-08 22:55:03 +08:00
rustdesk
fcf24e04bd Merge branch 'master' of https://github.com/rustdesk/rustdesk 2021-07-07 10:53:27 +08:00
rustdesk
2ec5fbb333 opacity 2021-07-07 10:53:13 +08:00
RustDesk
c1b241a8d1 Merge pull request #143 from SET19724/patch-2
Better translation pl readme
2021-07-07 00:38:27 +08:00
SET19724
b13aef98c2 Better translation
Not Polskie :)
Polski
2021-07-06 18:33:46 +02:00
RustDesk
b25c2c0551 Update README.md 2021-07-07 00:30:45 +08:00
rustdesk
e303a3b9b8 fix PL 2021-07-07 00:27:26 +08:00
RustDesk
ec8255b20f Merge pull request #142 from SET19724/patch-1
README-PL.md Tłumaczenie na Polski PL Polish
2021-07-07 00:23:57 +08:00
SET19724
529048bb8e Update README.md
City name fix
2021-07-06 18:23:28 +02:00
SET19724
926d3ca546 Tłumaczenie na Polski PL Polish
;)
2021-07-06 18:20:05 +02:00
rustdesk
7d316f9a51 https://github.com/rustdesk/rustdesk/issues/140 2021-07-06 10:47:49 +08:00
rustdesk
c27865d3ed change to dallas 2021-07-03 14:14:16 +08:00
rustdesk
d769b79a6f update servers 2021-07-03 10:27:34 +08:00
RustDesk
3aa4bdd1fa Merge pull request #137 from ToasterUwU/master
German README and correction of links in other MDs ("Deutsche" to "Deutsch")
2021-07-03 07:52:51 +08:00
mis1852
ad8b23d1a7 German README and correction of links in other mds 2021-07-02 19:29:26 +02:00
RustDesk
e8b8a260fd Merge pull request #128 from SantiagoValdez/patch-1
Update README.md - Fix spanish spelling
2021-06-29 08:52:58 +08:00
Santiago Valdez
b4467370a8 Update README.md - Fix spanish spelling
Spanish language is called Español or in some cases Castellano. 
Referring to Spanish language as 'Española' is not grammatically valid.
2021-06-28 17:14:01 -04:00
RustDesk
25ffaa7966 Merge pull request #122 from EmPablo/patch-2
Update : Panic message is not a string literal.
2021-06-26 12:18:07 +08:00
RustDesk
00b2b30778 Merge pull request #121 from EmPablo/patch-1
Update to the current release version number.
2021-06-26 12:17:49 +08:00
EmPablo
78692793a5 Update : Panic message is not a string literal. 2021-06-26 11:46:22 +08:00
EmPablo
5b9c90809c Update to the current release version number. 2021-06-26 11:43:38 +08:00
rustdesk
05c4dacbe9 ipc windows work 2021-06-26 01:14:22 +08:00
rustdesk
6f796db523 new namedpipe 2021-06-26 00:47:45 +08:00
rustdesk
2d515815ed Merge branch 'master' of https://github.com/rustdesk/rustdesk into master 2021-06-25 21:36:09 +08:00
rustdesk
dc3fcda2c9 tokio1, windows not test yet 2021-06-25 19:42:51 +08:00
RustDesk
25a83f6b4a Update README.md 2021-06-23 00:44:10 +08:00
RustDesk
086d1f9124 Add files via upload 2021-06-23 00:40:08 +08:00
rustdesk
5339b40104 ISSUE TEMPLATE 2021-06-22 11:34:07 +08:00
RustDesk
be9f0a22a0 Update README.md 2021-06-21 23:32:52 +08:00
RustDesk
fc3f76973d Update README.md 2021-06-21 23:32:07 +08:00
RustDesk
0d0c75e2a9 Merge pull request #101 from geshii/master
Create README-FR.md, French translation
2021-06-21 23:28:55 +08:00
Geshi
da7e044f16 Create README-FR.md 2021-06-21 16:16:37 +02:00
RustDesk
2ccbda2bb8 Update README-ES.md 2021-06-21 18:29:46 +08:00
RustDesk
87e161eddb Update README-ZH.md 2021-06-21 18:29:18 +08:00
RustDesk
592630fac4 Update README.md 2021-06-21 18:29:01 +08:00
RustDesk
aa67aab1f2 Merge pull request #97 from geshii/patch-1
Creating security guidelines, also known as SECURITY.md
2021-06-21 17:02:39 +08:00
Geshi
7e873f1c8b Create SECURITY.md 2021-06-21 10:56:43 +02:00
RustDesk
ba00e4daf2 Update README.md 2021-06-21 16:31:01 +08:00
RustDesk
8ef831ee5c Add files via upload 2021-06-21 16:27:16 +08:00
RustDesk
7cc5d138a0 Update README.md 2021-06-21 12:55:34 +08:00
RustDesk
7b4d5bc704 Update README.md 2021-06-21 12:49:05 +08:00
RustDesk
a4a09d5bfc Create README-ZH.md 2021-06-21 12:44:34 +08:00
RustDesk
c8465f9a5d Update README.md 2021-06-21 12:19:13 +08:00
RustDesk
2159423431 Update README.md 2021-06-21 12:18:56 +08:00
RustDesk
9d5cfb04ac Update README.md 2021-06-21 12:18:28 +08:00
RustDesk
43200f236a Merge pull request #94 from mtoohey31/docker-build
Support builds via Docker
2021-06-21 09:53:38 +08:00
mtoohey31
9383e4ecbb Support builds via Docker 2021-06-20 15:12:46 -04:00
RustDesk
6862406e68 Update README.md 2021-06-20 16:02:35 +08:00
RustDesk
c3b6dabcc8 Update README.md 2021-06-20 15:46:24 +08:00
RustDesk
a99e6f38e5 Merge pull request #89 from mtoohey31/display-server-fix
Check for Xorg running in tty
2021-06-20 12:02:05 +08:00
mtoohey31
142eebc9e2 https://github.com/rustdesk/rustdesk/issues/87 2021-06-19 14:35:40 -04:00
RustDesk
ec294451e3 Update README.md 2021-06-17 12:55:34 +08:00
RustDesk
7daeddf560 Update README.md 2021-06-17 12:55:11 +08:00
RustDesk
562b0c79dd Update README.md 2021-06-17 11:41:21 +08:00
RustDesk
b0f3ec40ce Update README.md 2021-06-17 11:41:07 +08:00
rustdesk
51903ede3d rs-ny.rustdesk.com 2021-06-15 11:21:10 +08:00
rustdesk
fda1e5e231 https://github.com/rustdesk/rustdesk/issues/58 2021-06-14 18:27:09 +08:00
rustdesk
e06217536b Merge branch 'master' of https://github.com/rustdesk/rustdesk into master 2021-06-14 17:52:33 +08:00
rustdesk
673986d045 https://github.com/rustdesk/rustdesk/issues/69 2021-06-14 17:51:45 +08:00
rustdesk
a2890fa548 https://github.com/rustdesk/rustdesk/issues/35 2021-06-14 15:29:36 +08:00
rustdesk
f3182a63e9 Merge branch 'master' of github.com:/rustdesk/rustdesk 2021-06-14 13:16:35 +08:00
rustdesk
a830922dea https://github.com/rustdesk/rustdesk/issues/73 2021-06-14 13:16:20 +08:00
RustDesk
ff54a98526 Merge pull request #71 from gitatmax/gitatmax-patch-1
Improved readability of OS list
2021-06-10 21:36:42 +08:00
Maxwell White
912053d99d Improved readability of OS list 2021-06-10 08:41:00 -04:00
rustdesk
da4669366b fix some rare case 2021-06-10 12:19:23 +08:00
rustdesk
c844d99ff1 try multiple time to get X11 env 2021-06-08 17:54:25 +08:00
rustdesk
369a9e0805 CONTRIBUTING.md 2021-06-07 13:44:21 +08:00
RustDesk
7daa080637 Update FUNDING.yml 2021-06-07 12:48:43 +08:00
RustDesk
e8606b8d0c Update README.md 2021-06-07 12:44:19 +08:00
rustdesk
ae9b6edf7c comment 2021-06-07 08:57:26 +08:00
rustdesk
34ce402203 https://github.com/rustdesk/rustdesk/issues/61 2021-06-06 16:27:02 +08:00
rustdesk
0ddfc32f0c refactor 2021-06-05 19:53:34 +08:00
RustDesk
c2d97054dd Merge pull request #60 from Candunc/master
Fixed typos, defaulted MacOS update prompt to use https
2021-06-05 08:03:03 +08:00
Duncan Bristow
155357a7e9 Fixed typos, defaulted MacOS update prompt to use https 2021-06-04 16:27:53 -07:00
RustDesk
14d35fc923 Merge pull request #57 from botiapa/master
Add --needed parameter to pacman install command
2021-06-05 00:10:17 +08:00
killswitch
913568a597 Add --needed parameter to pacman install command
This avoids reinstalling already installed packages.
2021-06-04 18:05:35 +02:00
rustdesk
1da5c1bde9 better linux support 2021-06-04 21:04:40 +08:00
rustdesk
31e6108f40 move confy here 2021-06-02 09:55:38 +08:00
rustdesk
ffcbc2abaa more for right key 2021-06-01 13:05:04 +08:00
rustdesk
5c541179dc update_pk if mismatch 2021-05-31 01:08:27 +08:00
RustDesk
ef6103da25 Update README.md 2021-05-28 13:26:48 +08:00
rustdesk
3be1971ca4 moved to rustdesk-server-demo repo 2021-05-27 22:57:52 +08:00
rustdesk
044f4cb12c demo server 2021-05-27 22:57:37 +08:00
RustDesk
cac416bcc0 Update README.md 2021-05-27 18:30:16 +08:00
rustdesk
8708fb366a righ key mapping and fix mac crash 2021-05-26 12:42:21 +08:00
rustdesk
d825d30e53 fix linux restore button and clipboard initial sync issue 2021-05-25 12:01:27 +08:00
rustdesk
002ca33cec Merge branch 'master' of https://github.com/rustdesk/rustdesk into master 2021-05-23 11:01:56 +08:00
rustdesk
7e1c56033b only dynamic 2021-05-23 11:01:27 +08:00
rustdesk
cd21f61d9c Merge branch 'master' of https://github.com/rustdesk/rustdesk into master 2021-05-23 10:57:49 +08:00
rustdesk
237e889604 move rust-sciter in 2021-05-23 10:55:19 +08:00
rustdesk
bdfb59dd1a remove unnessarey dns call 2021-05-23 00:14:00 +08:00
rustdesk
b7ab1405ee fix home path issue on some linux build 2021-05-21 19:11:09 +08:00
rustdesk
9a4786adb2 possible fix of mac crash 2021-05-20 17:19:37 +08:00
rustdesk
3a570de31e Merge branch 'master' of https://github.com/rustdesk/rustdesk into master 2021-05-20 17:16:01 +08:00
rustdesk
c5032f617b enable tray and fix install problems 2021-05-20 17:15:25 +08:00
rustdesk
d7b9c1aa72 enable tray and fix various install problems caused by format and
encoding
2021-05-20 17:06:25 +08:00
rustdesk
c05dd0b1b7 Merge branch 'master' of https://github.com/rustdesk/rustdesk into master 2021-05-17 20:46:31 +08:00
rustdesk
f760e56f79 better support for win7 2021-05-17 20:46:02 +08:00
rustdesk
7630713534 fix no audio issue with sample rate >= 48000 and strange crash issue
(there is some overflow in unsafe code, will test again)
2021-05-13 00:24:38 +08:00
rustdesk
5b2c1eea75 make intranet also secured 2021-05-11 20:34:04 +08:00
rustdesk
539cf03ad5 make local connection secured 2021-05-11 19:02:18 +08:00
RustDesk
1ce9d78c81 Merge pull request #30 from arthurhenrique/patch-1
doc: fix typos
2021-05-10 05:57:23 +08:00
Arthur Henrique
8528eb3aff doc: fix typos 2021-05-09 11:29:25 -03:00
rustdesk
49aeeffbe6 improve initial window size 2021-05-03 01:25:18 +08:00
rustdesk
8f5387c713 better fullscreen 2021-05-03 01:00:19 +08:00
rustdesk
dafc34dde5 fix fullscreen issue on linux 2021-05-03 00:50:50 +08:00
rustdesk
b5e8b9ee0d more fix on linux 2021-05-02 22:55:50 +08:00
rustdesk
2adc774d8a fix on linux 2021-05-02 21:19:48 +08:00
rustdesk
547b85adbf force to use static link for Manjaro 2021-05-02 00:37:32 +08:00
RustDesk
335ec619d9 Update README.md 2021-05-01 15:57:58 +08:00
RustDesk
0b5d9b63ea somebody report yasm needed also 2021-04-30 23:47:44 +08:00
RustDesk
9aac024267 About wayland 2021-04-30 00:41:20 +08:00
rustdesk
401648eefd fedora 2021-04-30 00:33:37 +08:00
RustDesk
afc842785a Update README.md 2021-04-29 11:49:30 +08:00
rustdesk
9c22ca4c6e wording 2021-04-29 09:35:23 +08:00
rustdesk
7a8cf58ab1 Merge branch 'master' of https://github.com/rustdesk/rustdesk into master 2021-04-26 11:46:36 +08:00
rustdesk
7b067ed28d recreate udp socket 2021-04-26 11:44:47 +08:00
228 changed files with 23784 additions and 9875 deletions

4
.cargo/config.toml Normal file
View File

@@ -0,0 +1,4 @@
[target.'cfg(target_os="macos")']
rustflags = [
"-C", "link-args=-sectcreate __CGPreLoginApp __cgpreloginapp /dev/null",
]

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
* text=auto

1
.github/FUNDING.yml vendored
View File

@@ -1 +1,2 @@
github: [rustdesk]
ko_fi: rustdesk

32
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,32 @@
---
name: Bug Report
about: Report a bug (English only, Please).
title: ""
labels: bug
assignees: ''
---
<!-- Hey there, thank you for creating an issue! -->
**Describe the bug you encountered:**
...
**What did you expect to happen instead?**
...
**How did you install `RustDesk`?**
<!-- GitHub release, build from source, Windows portable version, etc. -->
---
**RustDesk version and environment**
<!--
In order to reproduce your issue, please add some information about the environment
in which you're running RustDesk.
-->

2
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
blank_issues_enabled: true

View File

@@ -0,0 +1,10 @@
---
name: Feature Request
about: Suggest an idea for this project ((English only, Please).
title: ''
labels: feature-request
assignees: ''
---

10
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@@ -0,0 +1,10 @@
---
name: Question
about: Ask a question about 'RustDesk' (English only, Please).
title: ''
labels: question
assignees: ''
---

181
.github/workflows/ci.yml vendored Normal file
View 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}}

30
.github/workflows/snap-ci.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: Snap CI
on:
push:
branches:
- master
paths-ignore:
- README.md
tags:
- '*'
jobs:
build-snap-master-package:
runs-on: ubuntu-18.04
steps:
- name: Check out Git repository
uses: actions/checkout@v2
- name: Use Snapcraft
uses: snapcore/action-build@v1
id: build
- uses: actions/upload-artifact@v2
with:
name: rustdesk.snap
path: ${{ steps.build.outputs.snap }}
# - uses: snapcore/action-publish@v1
# with:
# store_login: ${{ secrets.SNAP_TOKEN }}
# snap: ${{ steps.build.outputs.snap }}
# release: edge

3
.gitignore vendored
View File

@@ -1,4 +1,5 @@
/target
.vscode
.idea
.DS_Store
src/ui/inline.rs
@@ -6,3 +7,5 @@ extractor
__pycache__
src/version.rs
*dmg
sciter.dll
**pdb

BIN
128x128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

BIN
128x128@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

133
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,133 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[info@rustdesk.com](mailto:info@rustdesk.com).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
at [https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

46
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,46 @@
# Contributing to RustDesk
RustDesk welcomes contribution from everyone. Here are the guidelines if you are
thinking of helping us:
## Contributions
Contributions to RustDesk or its dependencies should be made in the form of GitHub
pull requests. Each pull request will be reviewed by a core contributor
(someone with permission to land patches) and either landed in the main tree or
given feedback for changes that would be required. All contributions should
follow this format, even those from core contributors.
Should you wish to work on an issue, please claim it first by commenting on
the GitHub issue that you want to work on it. This is to prevent duplicated
efforts from contributors on the same issue.
## Pull Request Checklist
- Branch from the master branch and, if needed, rebase to the current master
branch before submitting your pull request. If it doesn't merge cleanly with
master you may be asked to rebase your changes.
- Commits should be as small as possible, while ensuring that each commit is
correct independently (i.e., each commit should compile and pass tests).
- Commits should be accompanied by a Developer Certificate of Origin
(http://developercertificate.org) sign-off, which indicates that you (and
your employer if applicable) agree to be bound by the terms of the
[project license](LICENSE). In git, this is the `-s` option to `git commit`
- If your patch is not getting reviewed or you need a specific person to review
it, you can @-reply a reviewer asking for a review in the pull request or a
comment, or you can ask for a review via [email](mailto:info@rustdesk.com).
- Add tests relevant to the fixed bug or new feature.
For specific git instructions, see [GitHub workflow 101](https://github.com/servo/servo/wiki/Github-workflow).
## Conduct
https://github.com/rustdesk/rustdesk/blob/master/CODE_OF_CONDUCT.md
## Communication
RustDesk contributors frequent the [Discord](https://discord.gg/nDceKgxnkV).

3555
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,58 +1,70 @@
[package]
name = "rustdesk"
version = "1.1.2"
version = "1.1.9"
authors = ["rustdesk <info@rustdesk.com>"]
edition = "2018"
edition = "2021"
build= "build.rs"
description = "A remote control software."
[lib]
crate-type = ["cdylib", "staticlib", "rlib"]
[features]
inline = []
cli = []
use_samplerate = ["samplerate"]
use_rubato = ["rubato"]
use_dasp = ["dasp"]
default = ["use_dasp"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
whoami = "0.9"
whoami = "1.2"
scrap = { path = "libs/scrap" }
hbb_common = { path = "libs/hbb_common" }
enigo = { path = "libs/enigo" }
clipboard = { path = "libs/clipboard" }
virtual_display = { path = "libs/virtual_display" }
sys-locale = "0.2"
serde_derive = "1.0"
serde = "1.0"
serde_json = "1.0"
cfg-if = "1.0"
lazy_static = "1.4"
sha2 = "0.9"
sha2 = "0.10"
repng = "0.2"
libc = "0.2"
parity-tokio-ipc = { path = "libs/parity-tokio-ipc" }
flexi_logger = "0.16"
parity-tokio-ipc = { git = "https://github.com/open-trade/parity-tokio-ipc" }
flexi_logger = { version = "0.22", features = ["async", "use_chrono_for_offset"] }
runas = "0.2"
magnum-opus = { path = "libs/magnum-opus" }
dasp = { version = "0.11", features = ["signal", "interpolate-linear", "interpolate"] }
magnum-opus = { git = "https://github.com/open-trade/magnum-opus" }
dasp = { version = "0.11", features = ["signal", "interpolate-linear", "interpolate"], optional = true }
rubato = { version = "0.12", optional = true }
samplerate = { version = "0.2", optional = true }
async-trait = "0.1"
crc32fast = "1.2"
uuid = { version = "0.8", features = ["v4"] }
copypasta = "0.7"
clap = "2.33"
rpassword = "5.0"
uuid = { version = "1.0.0", features = ["v4"] }
clap = "3.0"
rpassword = "6.0"
base64 = "0.13"
sysinfo = "0.23"
num_cpus = "1.13"
[target.'cfg(not(any(target_os = "android")))'.dependencies]
cpal = { git = "https://github.com/rustaudio/cpal" }
[target.'cfg(not(any(target_os = "android", target_os = "linux")))'.dependencies]
cpal = "0.13.5"
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
machine-uid = "0.2"
mac_address = "1.1"
sciter-rs = { git = "https://github.com/sciter-sdk/rust-sciter" }
sciter-rs = { git = "https://github.com/open-trade/rust-sciter", branch = "dyn" }
ctrlc = "3.2"
arboard = "2.0"
clipboard-master = "3.1"
#rdev = { path = "../rdev" }
rdev = { git = "https://github.com/open-trade/rdev" }
[target.'cfg(target_os = "windows")'.dependencies]
systray = { path = "libs/systray-rs" }
systray = { git = "https://github.com/liyue201/systray-rs" }
winapi = { version = "0.3", features = ["winuser"] }
winreg = "0.7"
windows-service = { git = 'https://github.com/mullvad/windows-service-rs.git' }
winreg = "0.10"
windows-service = "0.4"
[target.'cfg(target_os = "macos")'.dependencies]
objc = "0.2"
@@ -60,21 +72,19 @@ cocoa = "0.24"
dispatch = "0.2"
core-foundation = "0.9"
core-graphics = "0.22"
include_dir = "0.7.2"
tray-item = "0.7" # looks better than trayicon
[target.'cfg(target_os = "linux")'.dependencies]
libpulse-simple-binding = "2.16"
libpulse-binding = "2.16"
rust-pulsectl = { path = "libs/pulsectl" }
ctrlc = "3.1"
[target.'cfg(not(any(target_os = "windows", target_os = "android", target_os = "ios")))'.dependencies]
psutil = "3.2"
psimple = { package = "libpulse-simple-binding", version = "2.25" }
pulse = { package = "libpulse-binding", version = "2.26" }
rust-pulsectl = { git = "https://github.com/open-trade/pulsectl" }
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.9"
android_logger = "0.11"
[workspace]
members = ["libs/scrap", "libs/hbb_common", "libs/enigo"]
members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/clipboard", "libs/virtual_display"]
[package.metadata.winres]
LegalCopyright = "Copyright © 2020"
@@ -98,6 +108,7 @@ identifier = "com.carriez.rustdesk"
icon = ["32x32.png", "128x128.png", "128x128@2x.png"]
deb_depends = ["libgtk-3-0", "libxcb-randr0", "libxdo3", "libxfixes3", "libxcb-shape0", "libxcb-xfixes0", "libasound2", "libsystemd0", "pulseaudio"]
osx_minimum_system_version = "10.14"
resources = ["mac-tray.png"]
#https://github.com/johnthagen/min-sized-rust
#!!! rembember call "strip target/release/rustdesk"

19
DEBIAN/postinst Normal file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
set -e
if [ "$1" = configure ]; then
INITSYS=$(ls -al /proc/1/exe | awk -F' ' '{print $NF}' | awk -F'/' '{print $NF}')
if [ "systemd" == "$INITSYS" ]; then
if [ -e /etc/systemd/system/rustdesk.service ]; then
rm /etc/systemd/system/rustdesk.service
fi
sudo -H pip3 install pynput
cp /usr/share/rustdesk/files/systemd/rustdesk.service /etc/systemd/system/rustdesk.service
systemctl daemon-reload
systemctl enable rustdesk
systemctl start rustdesk
fi
fi

11
DEBIAN/postrm Normal file
View File

@@ -0,0 +1,11 @@
#!/bin/bash
set -e
case $1 in
purge)
rm -rf /root/.config/rustdesk || true
;;
esac
exit 0

16
DEBIAN/preinst Normal file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
set -e
case $1 in
install|upgrade)
INITSYS=$(ls -al /proc/1/exe | awk -F' ' '{print $NF}' | awk -F'/' '{print $NF}')
if [ "systemd" == "${INITSYS}" ]; then
service rustdesk stop || true
sleep 1
rm -rf /usr/bin/libsciter-gtk.so
fi
;;
esac
exit 0

16
DEBIAN/prerm Normal file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
set -e
case $1 in
remove|upgrade)
INITSYS=$(ls -al /proc/1/exe | awk -F' ' '{print $NF}' | awk -F'/' '{print $NF}')
if [ "systemd" == "${INITSYS}" ]; then
systemctl stop rustdesk || true
systemctl disable rustdesk || true
rm /etc/systemd/system/rustdesk.service || true
fi
;;
esac
exit 0

20
Dockerfile Normal file
View File

@@ -0,0 +1,20 @@
FROM debian
WORKDIR /
RUN apt update -y && 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 unzip zip sudo
RUN git clone https://github.com/microsoft/vcpkg && cd vcpkg && git checkout 134505003bb46e20fbace51ccfb69243fbbc5f82
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 && 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
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup.sh
RUN chmod +x rustup.sh
RUN ./rustup.sh -y
USER root
COPY ./entrypoint /
ENTRYPOINT ["/entrypoint"]

162
README-DE.md Normal file
View File

@@ -0,0 +1,162 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Your remote desktop"><br>
<a href="#kostenlose-öffentliche-server">Server</a> •
<a href="#die-groben-schritte-zum-kompilieren">Kompilieren</a> •
<a href="#auf-docker-kompilieren">Docker</a> •
<a href="#dateistruktur">Dateistruktur</a> •
<a href="#screenshots">Screenshots</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>Wir brauchen deine Hilfe um diese README Datei zu verbessern und aktualisieren</b>
</p>
Rede mit uns: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
Das hier ist ein Programm was, man nutzen kann, um einen Computer fernzusteuern, es wurde in Rust geschrieben. Es funktioniert ohne Konfiguration oder ähnliches, man kann es einfach direkt nutzen. Du hast volle Kontrolle über deine Daten und brauchst dir daher auch keine Sorgen um die Sicherheit dieser Daten zu machen. Du kannst unseren Rendezvous/Relay Server nutzen, [einen eigenen Server eröffnen](https://rustdesk.com/server) oder [einen neuen eigenen Server programmieren](https://github.com/rustdesk/rustdesk-server-demo).
RustDesk heißt jegliche Mitarbeit willkommen. Schau dir [`CONTRIBUTING.md`](CONTRIBUTING.md) an, wenn du Hilfe brauchst für den Start.
[**PROGRAMM DOWNLOAD**](https://github.com/rustdesk/rustdesk/releases)
## Kostenlose öffentliche Server
Hier sind die Server, die du kostenlos nutzen kannst, es kann sein das sich diese Liste immer mal wieder ändert. Falls du nicht in der Nähe einer dieser Server bist, kann es sein, dass deine Verbindung langsam sein wird.
| Standort | Serverart | Spezifikationen | Kommentare |
| --------- | ------------- | ------------------ | ---------- |
| Seoul | AWS lightsail | 1 VCPU / 0.5GB RAM | |
| Singapore | Vultr | 1 VCPU / 1GB RAM | |
| Dallas | Vultr | 1 VCPU / 1GB RAM | |
## Abhängigkeiten
Die Desktop-Versionen nutzen [Sciter](https://sciter.com/) für die Oberfläche, bitte lade die dynamische Sciter Bibliothek selbst herunter.
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## Die groben Schritte zum Kompilieren
- Bereite deine Rust Entwicklungsumgebung und C++ Entwicklungsumgebung vor
- Installiere [vcpkg](https://github.com/microsoft/vcpkg) und füge die `VCPKG_ROOT` Systemumgebungsvariable hinzu
- Windows: `vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static`
- Linux/MacOS: `vcpkg install libvpx libyuv opus`
- Nutze `cargo run`
## Kompilieren auf Linux
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### vcpkg installieren
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### libvpx reparieren (Für Fedora)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### Kompilieren
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
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:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
Jedes Mal, wenn du das Programm Kompilieren musst, nutze diesen Befehl:
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
Bedenke, dass das erste Mal Kompilieren länger dauern kann, da die Abhängigkeiten erst kompiliert werden müssen bevor sie zwischengespeichert werden können. Darauf folgende Kompiliervorgänge werden schneller sein. Falls du zusätzliche oder andere Argumente für den Kompilierbefehl angeben musst, kannst du diese am Ende des Befehls an der `<OPTIONAL-ARGS>` Position machen. Wenn du zum Beispiel eine optimierte Releaseversion kompilieren willst, kannst du das tun, indem du `--release` am Ende des Befehls anhängst. Das daraus entstehende Programm kannst du im “target” Ordner auf deinem System finden. Du kannst es mit folgenden Befehlen ausführen:
```sh
target/debug/rustdesk
```
Oder, wenn du eine Releaseversion benutzt:
```sh
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.
## 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
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: Bildschirmaufnahme
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: Plattformspezifische Maus und Tastatur Steuerung
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: Audio/Zwischenablage/Eingabe/Videodienste und Netzwerk Verbindungen
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: Starten einer Peer-Verbindung
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: Mit [rustdesk-server](https://github.com/rustdesk/rustdesk-server) kommunizieren, für Verbindung von außen warten, direkt (TCP hole punching) oder weitergeleitet
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: Plattformspezifischer Code
## Screenshots
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

161
README-EO.md Normal file
View File

@@ -0,0 +1,161 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Your remote desktop"><br>
<a href="#senpagaj-publikaj-serviloj">Serviloj</a> •
<a href="#paŝoj-por-kompili">Kompili</a> •
<a href="#kiel-kompili-kun-docker">Docker</a> •
<a href="#dosierstrukturo">Strukturo</a> •
<a href="#ekrankopio">Ekrankopio</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>Ni bezonas helpon traduki tiun README kaj <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang">la interfacon</a> al via denaska lingvo</b>
</p>
Babili kun ni: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
Denove alia fora labortabla programo, skribita en Rust. Ĝi funkcias elskatole, ne bezonas konfiguraĵon. Vi havas la tutan kontrolon sur viaj datumoj, sen zorgo pri sekureco. Vi povas uzi nian servilon rendezvous/relajsan, [agordi vian propran](https://rustdesk.com/server), aŭ [skribi vian propran servilon rendezvous/relajsan](https://github.com/rustdesk/rustdesk-server-demo).
RustDesk bonvenigas kontribuon de ĉiuj. Vidu [`CONTRIBUTING.md`](CONTRIBUTING.md) por helpo komenci.
[**BINARA ELŜUTO**](https://github.com/rustdesk/rustdesk/releases)
## Senpagaj publikaj serviloj
Malsupre estas la serviloj, kiuj vi uzas senpage, ĝi povas ŝanĝi laŭlonge de la tempo. Se vi ne estas proksima de unu de tiuj, via reto povas esti malrapida.
| Situo | Vendanto | Detaloj |
| --------- | ------------- | ------------------ |
| Seulo | AWS lightsail | 1 VCPU / 0.5GB RAM |
| Singapuro | Vultr | 1 VCPU / 1GB RAM |
| Dalaso | Vultr | 1 VCPU / 1GB RAM | |
## Dependantaĵoj
La labortabla versio uzas [sciter](https://sciter.com/) por la interfaco, bonvolu elŝuti la bibliotekon dinamikan sciter.
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## Paŝoj por kompili
- Preparu vian medion de programado Rust kaj vian medion de kompilado C++
- Instalu [vcpkg](https://github.com/microsoft/vcpkg), kaj agordu la medivariablon `VCPKG_ROOT` korekte
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Plenumu `cargo run`
## Kiel kompili sur Linukso
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### Instali vcpkg
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### Ripari libvpx (Por Fedora)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### Kompili
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
mv libsciter-gtk.so target/debug
VCPKG_ROOT=$HOME/vcpkg cargo run
```
### Ŝanĝi Wayland por X11 (Xorg)
RustDesk ne subtenas Wayland. Kontrolu [tion](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) por agordi Xorg kiel defaŭlta sesio GNOME.
## Kiel kompili kun Docker
Komencu klonante la deponejon kaj kompilu la konteneron Docker:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
Tiam, ĉiuj fojoj, kiuj vi bezonas kompili la programon, plenumu tiun komandon:
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
Notu, ke la unua kompilado povas daŭri longe, antaŭ ke la dependantaĵoj estu kaŝitaj, sekvaj kompiladoj estos pli rapidaj. Aldone, se vi bezonas specifi diferentajn argumentojn por la kompilkomando, vi povas fari ĝin en la fine de la komando, en la posicio `<OPTIONAL-ARGS>`. Ekzemple, se vi volas kompili version de eldono optimigita, vi plenumus la komandon supre, kun `---release`. La plenumebla dosiero disponeblos en la cela dosierujo sur via sistemo, kaj povos esti plenumita kun:
```sh
target/debug/rustdesk
```
Aŭ, se vi plenumas eldonan plenumeblan dosieron:
```sh
target/release/rustdesk
```
Bonvolu certigi, ke vi plenumas tiujn komandojn el la radiko de la deponejo RustDesk, alie la programo povus esti nekapabla de trovi la devigajn resursojn. Ankaŭ notu, ke la aliaj subkomandoj de cargo kiel `install``run` momente ne estas subtenitaj per tiu metodo, ĉar instalus aŭ plenumus la programon en la kontenero anstataŭ de la gastiganto.
## Dosierstrukturo
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: videa kodeko, agordado, kovrilo tcp/udp, protobuf, funkcioj fs por dosiertransigo, kaj aliaj utilaĵaj funkcioj
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: ekrankaptado
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: operaciumspecifa kontrolo de klavaro/muso
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: interfaco
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: aŭdio/poŝo/enigo/videa servoj, kaj retkonektoj
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: starti konekto kun samtavolo
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: komuniki kun [rustdesk-server](https://github.com/rustdesk/rustdesk-server), atendi foran direktan (TCP hole punching) aŭ relajsatan konekton
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: operaciumspecifa kodo
## Ekrankopio
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

160
README-ES.md Normal file
View File

@@ -0,0 +1,160 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Your remote desktop"><br>
<a href="#servidores-gratis-de-uso-público">Servidores</a> •
<a href="#pasos-para-compilar-desde-el-inicio">Compilar</a> •
<a href="#como-compilar-con-docker">Docker</a> •
<a href="#estructura-de-archivos">Estructura</a> •
<a href="#captura-de-pantalla">Captura de pantalla</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>Necesitamos tu ayuda para traducir este README a tu idioma</b>
</p>
Chat with us: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
Otro software de escritorio remoto, escrito en Rust. Funciona de forma inmediata, sin necesidad de configuración. Tienes el control total de sus datos, sin preocupaciones sobre la seguridad. Puedes utilizar nuestro servidor de rendezvous/relay, [set up your own](https://rustdesk.com/server), o [escribir tu propio servidor rendezvous/relay](https://github.com/rustdesk/rustdesk-server-demo).
RustDesk agradece la contribución de todo el mundo. Ve [`CONTRIBUTING.md`](CONTRIBUTING.md) para ayuda inicial.
[**DESCARGA DE BINARIOS**](https://github.com/rustdesk/rustdesk/releases)
## Servidores gratis de uso público
A continuación se muestran los servidores que está utilizando de forma gratuita, puede cambiar en algún momento. Si no estás cerca de uno de ellos, tu red puede ser lenta.
- Seoul, AWS lightsail, 1 VCPU/0.5G RAM
- Singapore, Vultr, 1 VCPU/1G RAM
- Dallas, Vultr, 1 VCPU/1G RAM
## Dependencies
La versión Desktop usa [sciter](https://sciter.com/) para GUI, por favor bajate la librería sciter tu mismo..
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[macOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## Pasos para compilar desde el inicio
- Prepara el entono de desarrollode Rust y el entorno de compilación de C++ y Rust.
- Instala [vcpkg](https://github.com/microsoft/vcpkg), y configura la variable de entono `VCPKG_ROOT` correctamente.
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/Osx: vcpkg install libvpx libyuv opus
- run `cargo run`
## Como compilar en linux
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### Install vcpkg
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### Soluciona libvpx (For Fedora)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### Compila
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
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:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
Entonces, cada vez que necesites compilar una modificación, ejecuta el siguiente comando:
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
Ten en cuenta que la primera compilación puede tardar más tiempo antes de que las dependencias se almacenen en la caché, las siguientes compilaciones serán más rápidas. Además, si necesitas especificar diferentes argumentos a la orden de compilación, puede hacerlo al final de la linea de comandos en el apartado`<OPTIONAL-ARGS>`. Por ejemplo, si desea compilar una versión optimizada para publicación, deberá ejecutar el comando anterior seguido de `---release`. El ejecutable resultante estará disponible en la carpeta de destino en su sistema, y puede ser ejecutado con:
```sh
target/debug/rustdesk
```
O si estas ejecutando una versión para su publicación:
```sh
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.
## 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.
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: captura de pantalla
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: control específico por cada plataforma para el teclado/ratón
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: sonido/portapapeles/entrada/servicios de video, y conexiones de red
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: iniciar una conexión "peer to peer"
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: Comunicación con [rustdesk-server](https://github.com/rustdesk/rustdesk-server), esperar la conexión remota directa ("TCP hole punching") o conexión indirecta ("relayed")
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: código específico de cada plataforma
## Captura de pantalla
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

161
README-FI.md Normal file
View File

@@ -0,0 +1,161 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Etätyöpöytäsi"><br>
<a href="#free-public-servers">Palvelimet</a> •
<a href="#raw-steps-to-build">Rakenna</a> •
<a href="#how-to-build-with-docker">Docker</a> •
<a href="#file-structure">Rakenne</a> •
<a href="#snapshot">Tilannevedos</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>Tarvitsemme apua tämän README-tiedoston kääntämiseksi äidinkielellesi</b>
</p>
Juttele meidän kanssa: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
Vielä yksi etätyöpöytäohjelmisto, ohjelmoitu Rust-kielellä. Toimii suoraan pakkauksesta, ei tarvitse asetuksia. Hallitset täysin tietojasi, ei tarvitse murehtia turvallisuutta. Voit käyttää meidän rendezvous/relay-palvelinta, [aseta omasi](https://rustdesk.com/server), tai [kirjoita oma rendezvous/relay-palvelin](https://github.com/rustdesk/rustdesk-server-demo).
RustDesk toivottaa avustukset tervetulleiksi kaikilta. Katso lisätietoja [`CONTRIBUTING.md`](CONTRIBUTING.md) avun saamiseksi.
[**BINAARILATAUS**](https://github.com/rustdesk/rustdesk/releases)
## Vapaita julkisia palvelimia
Alla on palvelimia, joita voit käyttää ilmaiseksi, ne saattavat muuttua ajan mittaan. Jos et ole lähellä yhtä näistä, verkkosi voi olla hidas.
| Sijainti | Myyjä | Määrittely |
| --------- | ------------- | ------------------ |
| Seoul | AWS lightsail | 1 VCPU / 0.5GB RAM |
| Singapore | Vultr | 1 VCPU / 1GB RAM |
| Dallas | Vultr | 1 VCPU / 1GB RAM | |
## Riippuvuudet
Desktop-versiot käyttävät [sciter](https://sciter.com/) graafisena käyttöliittymänä, lataa sciter-dynaaminen kirjasto itsellesi.
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## Rakentamisaskeleet harppoen
- Valmistele Rust-kehitysympäristö ja C++-rakentamisympäristö
- Asenna [vcpkg](https://github.com/microsoft/vcpkg), ja aseta `VCPKG_ROOT`-ympäristömuuttuja oikein
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- aja `cargo run`
## Kuinka rakentaa Linuxissa
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### Asenna vcpkg
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### Korjaa libvpx (Fedora-linux-versiota varten)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### Rakenna
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
mv libsciter-gtk.so target/debug
VCPKG_ROOT=$HOME/vcpkg cargo run
```
### Vaihda Wayland-ympäristö X11 (Xorg)-ympäristöön
RustDesk ei tue Waylandia. Tarkista [tämä](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) asettamaan Xorg oletus GNOME-istuntona.
## Kuinka rakennetaan Dockerin kanssa
Aloita kloonaamalla tietovarasto ja rakentamalla docker-säiliö:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
Sitten, joka kerta kun sinun on rakennettava sovellus, aja seuraava komento:
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
Huomaa, että ensimmäinen rakentaminen saattaa kestää pitempään ennen kuin riippuvuudet on siirretty välimuistiin, seuraavat rakentamiset ovat nopeampia. Lisäksi, jos sinun on määritettävä eri argumentteja rakentamiskomennolle, saatat tehdä sen niin, että komennon lopussa <OPTIONAL-ARGS>`-kohdassa. Esimerkiksi, jos haluat rakentaa optimoidun julkaisuversion, sinun on ajettava komento yllä siten, että sitä seuraa argumentti`---release`. Suoritettava tiedosto on saatavilla järjestelmäsi kohdehakemistossa, ja se voidaan suorittaa seuraavan kera:
```sh
target/debug/rustdesk
```
Tai, jos olet suorittamassa jakeluversion suoritettavaa tiedostoa:
```sh
target/release/rustdesk
```
Varmista, että suoritat näitä komentoja RustDesktop-tietovaraston juurihakemistossa, muutoin sovellus ei ehkä löydä vaadittuja resursseja. Huomaa myös, että muita cargo-alikomentoja kuten `install` tai `run` ei nykyisin tueta tässä menetelmässä, koska ne asentavat tai suorittavat ohjelman säiliön sisällä eikä isäntäohjelman sisällä.
## Tiedostorakenne
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: video codec, config, tcp/udp wrapper, protobuf, fs-funktiot tiedostosiirtoon, ja jotkut muut apuohjelmafunktiot
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: näyttökaappaukset
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: platform specific keyboard/mouse control
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: Graafinen käyttöliittymä
- **[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
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: Communicate with [rustdesk-server](https://github.com/rustdesk/rustdesk-server), wait for remote direct (TCP hole punching) or relayed connection
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: platform specific code
## Tilannekuvat
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

160
README-FR.md Normal file
View File

@@ -0,0 +1,160 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Your remote desktop"><br>
<a href="#serveurs-publics-libres">Serveurs</a> -
<a href="#étapes-brutes-de-la-compilationbuild">Build</a> -
<a href="#comment-construire-avec-docker">Docker</a> -
<a href="#structure-du-projet">Structure</a> -
<a href="#images">Images</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>Nous avons besoin de votre aide pour traduire ce README dans votre langue maternelle</b>.
</p>
Chattez avec nous : [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
Encore un autre logiciel de bureau à distance, écrit en Rust. Fonctionne directement, aucune configuration n'est nécessaire. Vous avez le contrôle total de vos données, sans aucun souci de sécurité. Vous pouvez utiliser notre serveur de rendez-vous/relais, [configurer le vôtre](https://rustdesk.com/server), ou [écrire votre propre serveur de rendez-vous/relais](https://github.com/rustdesk/rustdesk-server-demo).
RustDesk accueille les contributions de tout le monde. Voir [`CONTRIBUTING.md`](CONTRIBUTING.md) pour plus d'informations.
[**TÉLÉCHARGEMENT BINAIRE**](https://github.com/rustdesk/rustdesk/releases)
## Serveurs publics libres
Ci-dessous se trouvent les serveurs que vous utilisez gratuitement, cela peut changer au fil du temps. Si vous n'êtes pas proche de l'un d'entre eux, votre réseau peut être lent.
- Séoul, AWS lightsail, 1 VCPU/0.5G RAM
- Singapour, Vultr, 1 VCPU/1G RAM
- Dallas, Vultr, 1 VCPU/1G RAM
## Dépendances
Les versions de bureau utilisent [sciter](https://sciter.com/) pour l'interface graphique, veuillez télécharger la bibliothèque dynamique sciter vous-même.
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so)
[macOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## Étapes brutes de la compilation/build
- Préparez votre environnement de développement Rust et votre environnement de compilation C++.
- Installez [vcpkg](https://github.com/microsoft/vcpkg), et définissez correctement la variable d'environnement `VCPKG_ROOT`.
- Windows : vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/Osx : vcpkg install libvpx libyuv opus
- Exécuter `cargo run`
## Comment compiler/build sous Linux
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### Installer vcpkg
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### Corriger libvpx (Pour Fedora)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### Construire
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p cible/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
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 :
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
Ensuite, chaque fois que vous devez compiler le logiciel, exécutez la commande suivante :
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
Notez que la première compilation peut prendre plus de temps avant que les dépendances ne soient mises en cache, les compilations suivantes seront plus rapides. De plus, si vous devez spécifier différents arguments à la commande de compilation, vous pouvez le faire à la fin de la commande à la position `<OPTIONAL-ARGS>`. Par exemple, si vous voulez compiler une version de release optimisée, vous devez exécuter la commande ci-dessus suivie de `---release`. L'exécutable résultant sera disponible dans le dossier cible sur votre système, et peut être lancé avec :
```sh
target/debug/rustdesk
```
Ou, si vous exécutez un exécutable provenant d'une release :
```sh
target/release/rustdesk
```
Veuillez vous assurer que vous exécutez ces commandes à partir de la racine du dépôt 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.
## 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.
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)** : capture d'écran
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)** : contrôle clavier/souris spécifique à la plate-forme
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)** : interface graphique
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)** : services audio/clipboard/input/vidéo, et connexions réseau
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)** : démarrer une connexion entre pairs
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)** : Communiquer avec [rustdesk-server](https://github.com/rustdesk/rustdesk-server), attendre une connexion distante directe (TCP hole punching) ou relayée.
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)** : code spécifique à la plateforme
## Images
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

161
README-IT.md Normal file
View File

@@ -0,0 +1,161 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Your remote desktop"><br>
<a href="#server-pubblici-gratuiti">Servers</a> •
<a href="#passaggi-per-la-compilazione">Compilazione</a> •
<a href="#come-compilare-con-docker">Docker</a> •
<a href="#struttura-dei-file">Struttura</a> •
<a href="#screenshots">Screenshots</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>Abbiamo bisogno del tuo aiuto per tradurre questo README e la <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang">RustDesk UI</a> nella tua lingua nativa</b>
</p>
Chatta con noi: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
Ancora un altro software per il controllo remoto del desktop, scritto in Rust. Funziona immediatamente, nessuna configurazione richiesta. Hai il pieno controllo dei tuoi dati, senza preoccupazioni per la sicurezza. Puoi utilizzare il nostro server rendezvous/relay, [configurare il tuo](https://rustdesk.com/server) o [scrivere il tuo rendezvous/relay server](https://github.com/rustdesk/rustdesk-server-demo).
RustDesk accoglie il contributo di tutti. Per ulteriori informazioni su come inizare a contribuire, vedere [`CONTRIBUTING.md`](CONTRIBUTING.md).
[**BINARY DOWNLOAD**](https://github.com/rustdesk/rustdesk/releases)
## Server pubblici gratuiti
Qui sotto trovate i server che possono essere usati gratuitamente, la lista potrebbe cambiare nel tempo. Se non si è vicini a uno di questi server, la vostra connessione potrebbe essere lenta.
| Posizione | Vendor | Specifiche |
| --------- | ------------- | ------------------ |
| Seoul | AWS lightsail | 1 VCPU / 0.5GB RAM |
| Singapore | Vultr | 1 VCPU / 1GB RAM |
| Dallas | Vultr | 1 VCPU / 1GB RAM | |
## Dipendenze
La versione Desktop utilizza [sciter](https://sciter.com/) per la GUI, per favore scarica sciter dynamic library.
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## Passaggi per la compilazione
- Prepara l'ambiente per lo sviluppo e compilazione in Rust e C++
- Installa [vcpkg](https://github.com/microsoft/vcpkg), e imposta correttamente la variabile d'ambiente `VCPKG_ROOT`
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Esegui `cargo run`
## Come compilare su Linux
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### Installare vcpkg
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### Fix libvpx (Per Fedora)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### Compilazione
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
mv libsciter-gtk.so target/debug
VCPKG_ROOT=$HOME/vcpkg cargo run
```
### Cambiare Wayland a X11 (Xorg)
RustDesk non supporta Wayland. Controlla [questo](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) per configurare Xorg come sessione di default di GNOME.
## Come compilare con Docker
Cominciare clonando il repository e compilare i container docker:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
Quindi, ogni volta che devi compilare l'applicazione, esegui il comando seguente:
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
Tieni presente che la prima build potrebbe richiedere più tempo prima che le dipendenze vengano memorizzate nella cache, le build successive saranno più veloci. Inoltre, se hai bisogno di specificare argomenti diversi per il comando build, puoi farlo alla fine del comando nella posizione `<OPTIONAL-ARGS>`. Ad esempio, se si desidera creare una versione di rilascio ottimizzata, eseguire il comando sopra seguito da `---release`. L'eseguibile generato sarà creato nella cartella di destinazione del proprio sistema e può essere eseguito con:
```sh
target/debug/rustdesk
```
Oppure, se si sta eseguendo un eseguibile di rilascio:
```sh
target/release/rustdesk
```
Assicurati di eseguire questi comandi dalla radice del repository RustDesk, altrimenti l'applicazione potrebbe non essere in grado di trovare le risorse richieste. Notare inoltre che altri sottocomandi cargo come `install` o `run` non sono attualmente supportati tramite questo metodo poiché installerebbero o eseguirebbero il programma all'interno del container anziché nell'host.
## Struttura dei file
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: video codec, config, tcp/udp wrapper, protobuf, fs funzioni per il trasferimento file, e altre funzioni utili.
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: cattura dello schermo
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: controllo tastiera/mouse specifico della piattaforma
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: servizi audio/appunti/input/video e connessioni di rete
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: avviare una connessione peer
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: Comunica con [rustdesk-server](https://github.com/rustdesk/rustdesk-server), attende la connessione remota diretta (TCP hole punching) oppure indiretta (relayed)
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: codice specifico della piattaforma
## Screenshots
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

163
README-JP.md Normal file
View File

@@ -0,0 +1,163 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Your remote desktop"><br>
<a href="#free-public-servers">Servers</a> •
<a href="#raw-steps-to-build">Build</a> •
<a href="#how-to-build-with-docker">Docker</a> •
<a href="#file-structure">Structure</a> •
<a href="#snapshot">Snapshot</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>このREADMEをあなたの母国語に翻訳するために、あなたの助けが必要です。</b>
</p>
Chat with us: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
Rustで書かれた、設定不要ですぐに使えるリモートデスクトップソフトウェアです。自分のデータを完全にコントロールでき、セキュリティの心配もありません。私たちのランデブー/リレーサーバを使うことも、[自分で設定する](https://rustdesk.com/server) ことも、 [自分でランデブー/リレーサーバを書くこともできます。](https://github.com/rustdesk/rustdesk-server-demo).
RustDeskは誰からの貢献も歓迎します。 貢献するには [`CONTRIBUTING.md`](CONTRIBUTING.md) を参照してください。
[**BINARY DOWNLOAD**](https://github.com/rustdesk/rustdesk/releases)
## 無料のパブリックサーバー
下記のサーバーは、無料で使用できますが、後々変更されることがあります。これらのサーバーから遠い場合、接続が遅い可能性があります。
| Location | Vendor | Specification |
| --------- | ------------- | ------------------ |
| Seoul | AWS lightsail | 1 VCPU / 0.5GB RAM |
| Singapore | Vultr | 1 VCPU / 1GB RAM |
| Dallas | Vultr | 1 VCPU / 1GB RAM | |
## 依存関係
デスクトップ版ではGUIに [sciter](https://sciter.com/) が使われています。 sciter dynamic library をダウンロードしてください。
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## ビルド手順
- Rust開発環境とC ++ビルド環境を準備します
- [vcpkg](https://github.com/microsoft/vcpkg), をインストールし、 `VCPKG_ROOT` 環境変数を正しく設定します。
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- run `cargo run`
## Linuxでのビルド手順
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### Install vcpkg
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### Fix libvpx (For Fedora)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### Build
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
mv libsciter-gtk.so target/debug
VCPKG_ROOT=$HOME/vcpkg cargo run
```
### Wayland の場合、X11Xorgに変更します
RustDeskはWaylandをサポートしていません。
[こちら](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) を確認して、XorgをデフォルトのGNOMEセッションとして構成します。
## Dockerでビルドする方法
リポジトリのクローンを作成し、Dockerコンテナを構築することから始めます。
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
その後、アプリケーションをビルドする必要があるたびに、以下のコマンドを実行します。
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
なお、最初のビルドでは、依存関係がキャッシュされるまで時間がかかることがありますが、その後のビルドではより速くなります。さらに、ビルドコマンドに別の引数を指定する必要がある場合は、コマンドの最後にある `<OPTIONAL-ARGS>` の位置で指定することができます。例えば、最適化されたリリースバージョンをビルドしたい場合は、上記のコマンドの後に
`---release` を実行します。できあがった実行ファイルは、システムのターゲット・フォルダに格納され、次のコマンドで実行できます。
```sh
target/debug/rustdesk
```
あるいは、リリース用の実行ファイルを実行している場合:
```sh
target/release/rustdesk
```
これらのコマンドをRustDeskリポジトリのルートから実行していることを確認してください。そうしないと、アプリケーションが必要なリソースを見つけられない可能性があります。また、 `install``run` などの他の cargo サブコマンドは、ホストではなくコンテナ内にプログラムをインストールまたは実行するため、現在この方法ではサポートされていないことに注意してください。
## File Structure
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: ビデオコーデック、コンフィグ、tcp/udpラッパー、protobuf、ファイル転送用のfs関数、その他のユーティリティ関数
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: スクリーンキャプチャ
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: プラットフォーム固有のキーボード/マウスコントロール
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: オーディオ/クリップボード/入力/ビデオサービス、ネットワーク接続
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: ピア接続の開始
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: [rustdesk-server](https://github.com/rustdesk/rustdesk-server), と通信し、リモートダイレクト (TCP hole punching) または中継接続を待つ。
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: プラットフォーム固有のコード
## Snapshot
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

161
README-ML.md Normal file
View File

@@ -0,0 +1,161 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Your remote desktop"><br>
<a href="#free-public-servers">Servers</a> •
<a href="#raw-steps-to-build">Build</a> •
<a href="#how-to-build-with-docker">Docker</a> •
<a href="#file-structure">Structure</a> •
<a href="#snapshot">Snapshot</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>ഈ README നിങ്ങളുടെ മാതൃഭാഷയിലേക്ക് വിവർത്തനം ചെയ്യാൻ ഞങ്ങൾക്ക് നിങ്ങളുടെ സഹായം ആവശ്യമാണ്</b>
</p>
ഞങ്ങളുമായി ചാറ്റ് ചെയ്യുക: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
റസ്റ്റിൽ എഴുതിയ മറ്റൊരു റിമോട്ട് ഡെസ്ക്ടോപ്പ് സോഫ്റ്റ്‌വെയർ. ബോക്‌സിന് പുറത്ത് പ്രവർത്തിക്കുന്നു, കോൺഫിഗറേഷൻ ആവശ്യമില്ല. സുരക്ഷയെക്കുറിച്ച് ആശങ്കകളൊന്നുമില്ലാതെ, നിങ്ങളുടെ ഡാറ്റയുടെ പൂർണ്ണ നിയന്ത്രണം നിങ്ങൾക്കുണ്ട്. നിങ്ങൾക്ക് ഞങ്ങളുടെ rendezvous/relay സെർവർ ഉപയോഗിക്കാം, [സ്വന്തമായി സജ്ജീകരിക്കുക](https://rustdesk.com/server), അല്ലെങ്കിൽ [നിങ്ങളുടെ സ്വന്തം rendezvous/relay സെർവർ എഴുതുക](https://github.com/rustdesk/rustdesk-server-demo).
എല്ലാവരുടെയും സംഭാവനയെ RustDesk സ്വാഗതം ചെയ്യുന്നു. ആരംഭിക്കുന്നതിനുള്ള സഹായത്തിന് [`CONTRIBUTING.md`](CONTRIBUTING.md) കാണുക.
[**BINARY DOWNLOAD**](https://github.com/rustdesk/rustdesk/releases)
## സൗജന്യ പൊതു സെർവറുകൾ
നിങ്ങൾ സൗജന്യമായി ഉപയോഗിക്കുന്ന സെർവറുകൾ ചുവടെയുണ്ട്, അത് സമയത്തിനനുസരിച്ച് മാറിയേക്കാം. നിങ്ങൾ ഇവയിലൊന്നിനോട് അടുത്തല്ലെങ്കിൽ, നിങ്ങളുടെ നെറ്റ്‌വർക്ക് സ്ലോ ആയേക്കാം.
| സ്ഥാനം | കച്ചവടക്കാരൻ | വിവരണം |
| --------- | ------------- | ------------------ |
| Seoul | AWS lightsail | 1 VCPU / 0.5GB RAM |
| Singapore | Vultr | 1 VCPU / 1GB RAM |
| Dallas | Vultr | 1 VCPU / 1GB RAM | |
## ഡിപെൻഡൻസികൾ
ഡെസ്‌ക്‌ടോപ്പ് പതിപ്പുകൾ GUI-യ്‌ക്കായി [sciter](https://sciter.com/) ഉപയോഗിക്കുന്നു, ദയവായി സ്‌സൈറ്റർ ഡൈനാമിക് ലൈബ്രറി സ്വയം ഡൗൺലോഡ് ചെയ്യുക.
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## നിർമ്മിക്കാനുള്ള അസംസ്കൃത പടികൾ
- നിങ്ങളുടെ Rust development envയു and C++ build envയു തയ്യാറാക്കുക
- [vcpkg](https://github.com/microsoft/vcpkg) ഇൻസ്റ്റാൾ ചെയ്ത് `VCPKG_ROOT` env വേരിയബിൾ ശരിയായി സജ്ജമാക്കുക
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- run `cargo run`
## ലിനക്സിൽ എങ്ങനെ നിർമ്മിക്കാം
### ഉബുണ്ടു 18 (ഡെബിയൻ 10)
```sh
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
```
### ഫെഡോറ 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### ആർച് (മഞ്ചാരോ)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### vcpkg ഇൻസ്റ്റാൾ ചെയ്യുക
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### libvpx പരിഹരിക്കുക (ഫെഡോറയ്ക്ക്)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### നിർമാണം
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
mv libsciter-gtk.so target/debug
VCPKG_ROOT=$HOME/vcpkg cargo run
```
### വേലാൻഡ് X11 (Xorg) ആയി മാറ്റുക
RustDesk Wayland-നെ പിന്തുണയ്ക്കുന്നില്ല. സ്ഥിരസ്ഥിതി ഗ്നോം സെഷനായി Xorg കോൺഫിഗർ ചെയ്യുന്നതിന് [ഇത്](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) പരിശോധിക്കുക.
## ഡോക്കർ ഉപയോഗിച്ച് എങ്ങനെ നിർമ്മിക്കാം
റെപ്പോസിറ്റോറി ക്ലോണുചെയ്‌ത് ഡോക്കർ കണ്ടെയ്‌നർ നിർമ്മിക്കുന്നതിലൂടെ ആരംഭിക്കുക:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
തുടർന്ന്, ഓരോ തവണയും നിങ്ങൾ ആപ്ലിക്കേഷൻ നിർമ്മിക്കേണ്ടതുണ്ട്, ഇനിപ്പറയുന്ന കമാൻഡ് പ്രവർത്തിപ്പിക്കുക:
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
ഡിപൻഡൻസികൾ കാഷെ ചെയ്യുന്നതിനുമുമ്പ് ആദ്യ ബിൽഡ് കൂടുതൽ സമയമെടുത്തേക്കാം, തുടർന്നുള്ള ബിൽഡുകൾ വേഗത്തിലാകും. കൂടാതെ, നിങ്ങൾക്ക് ബിൽഡ് കമാൻഡിലേക്ക് വ്യത്യസ്ത ആർഗ്യുമെന്റുകൾ വ്യക്തമാക്കണമെങ്കിൽ, കമാൻഡിന്റെ അവസാനം `<OPTIONAL-ARGS>` സ്ഥാനത്ത് നിങ്ങൾക്ക് അങ്ങനെ ചെയ്യാം. ഉദാഹരണത്തിന്, നിങ്ങൾ ഒരു ഒപ്റ്റിമൈസ് ചെയ്ത റിലീസ് പതിപ്പ് നിർമ്മിക്കാൻ ആഗ്രഹിക്കുന്നുവെങ്കിൽ, മുകളിലുള്ള കമാൻഡ് തുടർന്ന് `---release` നിങ്ങൾ പ്രവർത്തിപ്പിക്കും. തത്ഫലമായുണ്ടാകുന്ന എക്സിക്യൂട്ടബിൾ നിങ്ങളുടെ സിസ്റ്റത്തിലെ ടാർഗെറ്റ് ഫോൾഡറിൽ ലഭ്യമാകും, കൂടാതെ ഇത് ഉപയോഗിച്ച് പ്രവർത്തിപ്പിക്കാം:
```sh
target/debug/rustdesk
```
അല്ലെങ്കിൽ, നിങ്ങൾ ഒരു റിലീസ് എക്സിക്യൂട്ടബിൾ പ്രവർത്തിപ്പിക്കുകയാണെങ്കിൽ:
```sh
target/release/rustdesk
```
RustDesk റിപ്പോസിറ്ററിയുടെ റൂട്ടിൽ നിന്നാണ് നിങ്ങൾ ഈ കമാൻഡുകൾ പ്രവർത്തിപ്പിക്കുന്നതെന്ന് ദയവായി ഉറപ്പാക്കുക, അല്ലാത്തപക്ഷം ആപ്ലിക്കേഷന് ആവശ്യമായ ഉറവിടങ്ങൾ കണ്ടെത്താൻ കഴിഞ്ഞേക്കില്ല. ഹോസ്റ്റിന് പകരം കണ്ടെയ്‌നറിനുള്ളിൽ പ്രോഗ്രാം ഇൻസ്റ്റാൾ ചെയ്യുകയോ പ്രവർത്തിപ്പിക്കുകയോ ചെയ്യുന്നതിനാൽ, `install` അല്ലെങ്കിൽ `run` പോലുള്ള മറ്റ് കാർഗോ സബ്‌കമാൻഡുകൾ നിലവിൽ ഈ രീതിയെ പിന്തുണയ്ക്കുന്നില്ല എന്നതും ശ്രദ്ധിക്കുക.
## ഫയൽ ഘടന
- **[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
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
- **[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
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: Communicate with [rustdesk-server](https://github.com/rustdesk/rustdesk-server), wait for remote direct (TCP hole punching) or relayed connection
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: platform specific code
## സ്നാപ്പ്ഷോട്ടുകൾ
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

163
README-NL.md Normal file
View File

@@ -0,0 +1,163 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Jouw verbinding op afstand"><br>
<a href="#free-public-servers">Servers</a> •
<a href="#raw-steps-to-build">Bouwen</a> •
<a href="#how-to-build-with-docker">Docker</a> •
<a href="#file-structure">Structuur</a> •
<a href="#snapshot">Snapshot</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>We hebben je hulp nodig om deze README te vertalen naar jouw moedertaal</b>
</p>
Praat met ons: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
Nog weer een applicatie voor toegang op afstand, geschreven in Rust. Werkt meteen, geen configuratie nodig. Je hebt volledig beheer over je data, zonder na te hoeven denken over veiligheid. Je kunt onze rendez-vous/relay-server gebruiken, [je eigen server opzetten](https://rustdesk.com/blog/id-relay-set), of [je eigen rendez-vous/relay-server schrijven](https://github.com/rustdesk/rustdesk-server-demo).
RustDesk verwelkomt bijdragen van iedereen. Zie [`CONTRIBUTING.md`](CONTRIBUTING.md) om te lezen hoe je van start kunt gaan.
[**BINARY DOWNLOAD**](https://github.com/rustdesk/rustdesk/releases)
## Gratis openbare servers
Onderstaande servers zijn de servers die je gratis kunt gebruiken, ze kunnen op termijn veranderen. Als je niet fysiek dichtbij een van deze servers bent, kan je verbinding traag werken.
| Locatie | Aanbieder | Specificaties |
| --------- | ------------- | ------------------ |
| Seoul | AWS lightsail | 1 VCPU / 0.5GB RAM |
| Singapore | Vultr | 1 VCPU / 1GB RAM |
| Dallas | Vultr | 1 VCPU / 1GB RAM | |
## Afhankelijkheden
Desktopversies gebruiken [sciter](https://sciter.com/) voor de grafische schil. Gelieve zelf de sciter-library te downloaden.
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## Handmatige bouwinstructies
- Bereid je Rust-ontwikkelomgeving en C++-bouwomgeving voor.
- Installeer [vcpkg](https://github.com/microsoft/vcpkg) en configureer de `VCPKG_ROOT` omgevingsvariabele op de juiste manier:
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Voer uit: `cargo run`
## Bouwen op Linux
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### Installatie van vcpkg
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### Fix voor libvpx (voor Fedora)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### Bouwen
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
mv libsciter-gtk.so target/debug
VCPKG_ROOT=$HOME/vcpkg cargo run
```
### Wissel van Wayland naar X11 (Xorg)
RustDesk ondersteunt Wayland niet. Lees [hier](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) hoe je Xorg als standaardsessie kunt instellen voor GNOME.
## Bouwen met Docker
Kloon eerst deze repository en bouw de Docker-container:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
Voer vervolgens de volgende commando's uit iedere keer dat je de applicatie opnieuw moet bouwen:
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
Let op dat de eerste build langer kan duren omdat de dependencies nog niet zijn gecached; latere builds zullen sneller zijn. Als je extra command line arguments wilt toevoegen aan het build-commando, dan kun je dat doen aan het einde van de opdrachtregel in plaats van `<OPTIONAL-ARGS>`. Bijvoorbeeld: als je een geoptimaliseerde releaseversie wilt bouwen, draai dan het bovenstaande commando gevolgd door `---release`.
Het uitvoerbare bestand, in debug-modus, zal verschijnen in de target-map, en kan als volgt worden uitgevoerd:
```sh
target/debug/rustdesk
```
Als je een release-versie hebt gebouwd, is het commando als volgt:
```sh
target/release/rustdesk
```
Zorg ervoor dat je deze commando's van de root van de RustDesk-repository uitvoert, anders kan het programma de nodige afhankelijkheden mogelijk niet vinden. Let ook op dat andere cargo-subcommando's zoals `install` en `run` zijn momenteel niet ondersteund, aangezien deze zouden worden uitgevoerd in een container in plaats van op de host.
## Bestandsstructuur
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: videocodec, configuratie, TCP/UDP-wrapper, protobuf, bestandssysteemfuncties voor bestandsoverdracht en nog wat andere nuttige functies
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: schermopname
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: platformspecifieke muis- en toetsenbordbeheer
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: geluids-, klembord-, invoer- en video-services, netwerkverbindingen
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: voor het opzetten van peer-verbindingen
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: Communicatie met [rustdesk-server](https://github.com/rustdesk/rustdesk-server), afwachten van redirect op afstand (TCP hole punching) of een relayed verbinding
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: platformspecifieke code
## Snapshot
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

161
README-PL.md Normal file
View File

@@ -0,0 +1,161 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Your remote desktop"><br>
<a href="#darmowe-serwery-publiczne">Serwery</a> •
<a href="#podstawowe-kroki-do-kompilacji">Kompilacja</a> •
<a href="#jak-kompilować-za-pomocą-dockera">Docker</a> •
<a href="#struktura-plików">Struktura</a> •
<a href="#migawkisnapshoty">Snapshot</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>Potrzebujemy twojej pomocy w tłumaczeniu README na twój ojczysty język</b>
</p>
Porozmawiaj z nami na: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
Kolejny program do zdalnego pulpitu, napisany w Rust. Działa od samego początku, nie wymaga konfiguracji. Masz pełną kontrolę nad swoimi danymi, bez obaw o bezpieczeństwo. Możesz skorzystać z naszego darmowego serwera publicznego , [skonfigurować własny](https://rustdesk.com/server), lub [napisać własny serwer rendezvous/relay server](https://github.com/rustdesk/rustdesk-server-demo).
RustDesk zaprasza do współpracy każdego. Zobacz [`CONTRIBUTING.md`](CONTRIBUTING.md) pomoc w uruchomieniu programu.
[**POBIERZ KOMPILACJE**](https://github.com/rustdesk/rustdesk/releases)
## Darmowe Serwery Publiczne
Poniżej znajdują się serwery, z których można korzystać za darmo, może się to zmienić z upływem czasu. Jeśli nie znajdujesz się w pobliżu jednego z nich, Twoja prędkość połączenia może być niska.
| Lokalizacja | Dostawca | Specyfikacja |
| --------- | ------------- | ------------------ |
| Seul | AWS lightsail | 1 VCPU / 0.5GB RAM |
| Singapur | Vultr | 1 VCPU / 1GB RAM |
| Dallas | Vultr | 1 VCPU / 1GB RAM | |
## Zależności
Wersje desktopowe używają [sciter](https://sciter.com/) dla GUI, proszę pobrać bibliotekę dynamiczną sciter samodzielnie.
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## Podstawowe kroki do kompilacji
- Przygotuj środowisko programistyczne Rust i środowisko programowania C++
- Zainstaluj [vcpkg](https://github.com/microsoft/vcpkg), i ustaw `VCPKG_ROOT` env zmienną prawidłowo
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- uruchom `cargo run`
## Jak Kompilować na Linuxie
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### Zainstaluj vcpkg
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### Fix libvpx (For Fedora)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### Kompilacja
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
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:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
Następnie, za każdym razem, gdy potrzebujesz skompilować aplikację, uruchom następujące polecenie:
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
Zauważ, że pierwsza kompilacja może potrwać dłużej zanim zależności zostaną zbuforowane, kolejne będą szybsze. Dodatkowo, jeśli potrzebujesz określić inne argumenty dla polecenia budowania, możesz to zrobić na końcu komendy w miejscu `<OPTIONAL-ARGS>`. Na przykład, jeśli chciałbyś zbudować zoptymalizowaną wersję wydania, uruchomiłbyś powyższą komendę a następnie `---release`. Powstały plik wykonywalny będzie dostępny w folderze docelowym w twoim systemie, i może być uruchomiony z:
```sh
target/debug/rustdesk
```
Lub, jeśli uruchamiasz plik wykonywalny wersji:
```sh
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.
## 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
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: przechwytywanie ekranu
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: specyficzne dla danej platformy sterowanie klawiaturą/myszą
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: audio/schowek/wejście(input)/wideo oraz połączenia sieciowe
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: uruchamia połączenie peer
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: Komunikacja z [rustdesk-server](https://github.com/rustdesk/rustdesk-server), wait for remote direct (TCP hole punching) or relayed connection
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: specyficzny dla danej platformy kod
## Migawki(Snapshoty)
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

162
README-PTBR.md Normal file
View File

@@ -0,0 +1,162 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Seu desktop remoto"><br>
<a href="#servidores-públicos-grátis">Servidores</a> •
<a href="#compilação-crua">Compilar</a> •
<a href="#como-compilar-com-docker">Docker</a> •
<a href="#estrutura-de-arquivos">Estrutura</a> •
<a href="#screenshots">Screenshots</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>Precisamos de sua ajuda para traduzir este README e a <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang">UI do RustDesk</a> para sua língua nativa</b>
</p>
Converse conosco: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
Mais um software de desktop remoto, escrito em Rust. Funciona por padrão, sem necessidade de configuração. Você tem completo controle de seus dados, sem se preocupar com segurança. Você pode usar nossos servidores de rendezvous/relay, [configurar seu próprio](https://rustdesk.com/server), ou [escrever seu próprio servidor de rendezvous/relay](https://github.com/rustdesk/rustdesk-server-demo).
RustDesk acolhe contribuições de todos. Leia [`CONTRIBUTING.md`](CONTRIBUTING.md) para ver como começar.
[**DOWNLOAD DE BINÁRIOS**](https://github.com/rustdesk/rustdesk/releases)
## Servidores Públicos Grátis
Abaixo estão os servidores que você está utilizando de graça, ele pode mudar com o tempo. Se você não está próximo de algum deles, sua conexão pode ser lenta.
| Localização | Fornecedor | Especificações |
| ----------- | ------------- | ------------------ |
| Seul | AWS lightsail | 1 VCPU / 0.5GB RAM |
| Singapura | Vultr | 1 VCPU / 1GB RAM |
| Dallas | Vultr | 1 VCPU / 1GB RAM |
## Dependências
Versões de desktop utilizam [sciter](https://sciter.com/) para a GUI, por favor baixe a biblioteca dinâmica sciter por conta própria.
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## Compilação crua
- Prepare seu ambiente de desenvolvimento Rust e ambiente de compilação C++
- Instale [vcpkg](https://github.com/microsoft/vcpkg), e configure a variável de ambiente `VCPKG_ROOT` corretamente
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Execute `cargo run`
## Como compilar no Linux
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### Instale vcpkg
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### Conserte libvpx (Para o Fedora)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### Compile
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
mv libsciter-gtk.so target/debug
VCPKG_ROOT=$HOME/vcpkg cargo run
```
### Mude Wayland para X11 (Xorg)
RustDesk não suporta Wayland. Veja [esse link](https://docs.fedoraproject.org/pt_BR/quick-docs/configuring-xorg-as-default-gnome-session/) para configurar o Xorg como a sessão padrão do GNOME.
## Como compilar com Docker
Comece clonando o repositório e montando o container docker:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
Então, sempre que precisar compilar a aplicação, execute este comando:
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
Note que a primeira compilação pode demorar mais antes que as dependências sejam armazenadas em cache, as compilações subsequentes serão mais rápidas. Adicionalmente, se você precisar especificar argumentos diferentes para o comando de compilação, você pode fazê-lo ao final do comando na posição do `<OPTIONAL-ARGS>`. Por exemplo, se você gostaria de compilar uma versão de release otimizada, você executaria o comando acima seguido de `--release`. O executável gerado estará disponível no diretório alvo no seu sistema, e pode ser executado com:
```sh
target/debug/rustdesk
```
Ou, se estiver rodando um executável de release:
```sh
target/release/rustdesk
```
Por favor verifique que está executando estes comandos da raiz do repositório do RustDesk, senão a aplicação pode não encontrar os recursos necessários. Note também que outros subcomandos do cargo como `install` ou `run` não são suportados atualmente via este método, já que eles iriam instalar ou rodar o programa dentro do container ao invés do host.
## Estrutura de arquivos
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: codec de vídeo, configurações, wrapper de tcp/udp, protobuf, funções de sistema de arquivos para transferência de arquivos, e outras funções utilitárias
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: captura de tela
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: controle de teclado/mouse específico a cada plataforma
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: serviços de áudio/área de transferência/entrada/vídeo, e conexões de rede
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: iniciar uma conexão "peer to peer"
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: Comunicação com [rustdesk-server](https://github.com/rustdesk/rustdesk-server), aguardar pela conexão remota direta (TCP hole punching) ou conexão indireta (relayed)
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: código específico a cada plataforma
## Screenshots
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

161
README-RU.md Normal file
View File

@@ -0,0 +1,161 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Your remote desktop"><br>
<a href="#free-public-servers">Servers</a> •
<a href="#raw-steps-to-build">Build</a> •
<a href="#how-to-build-with-docker">Docker</a> •
<a href="#file-structure">Structure</a> •
<a href="#snapshot">Snapshot</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>Нам нужна ваша помощь для перевода этого README и <a href="https://github.com/rustdesk/rustdesk/tree/master/src/rustdesk/tree/master/src/lang">RustDesk UI</a> на ваш родной язык</B>
</p>
Общение с нами: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
Еще одно программное обеспечение для удаленного рабочего стола, написанное на Rust. Работает из коробки, не требует настройки. Вы полностью контролируете свои данные, не беспокоясь о безопасности. Вы можете использовать наш сервер ретрансляции, [настроить свой собственный](https://rustdesk.com/server), или [написать свой собственный сервер ретрансляции](https://github.com/rustdesk/rustdesk-server-demo).
RustDesk приветствует вклад каждого. Смотри [`CONTRIBUTING.md`](CONTRIBUTING.md) для помощи в начале работы.
[**СКАЧАТЬ ПРИЛОЖЕНИЕ**](https://github.com/rustdesk/rustdesk/releases)
## Бесплатные общедоступные серверы
Ниже приведены серверы, для бесплатного использования, они могут меняться со временем. Если вы не находитесь рядом с одним из них, ваша сеть может работать медленно.
| Местонахождение | Поставщик | Технические характеристики |
| --------- | ------------- | ------------------ |
| Сеул | AWS lightsail | 1 VCPU / 0.5GB RAM |
| Сингапур | Vultr | 1 VCPU / 1GB RAM |
| Даллас | Vultr | 1 VCPU / 1GB RAM | |
## Зависимости
Настольные версии используют [sciter](https://sciter.com/) для графического интерфейса, загрузите динамическую библиотеку sciter самостоятельно.
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## Необработанные шаги для сборки
- Подготовьте среду разработки Rust и среду сборки C++.
- Установите [vcpkg](https://github.com/microsoft/vcpkg), и правильно установите переменную `VCPKG_ROOT`
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Запустите`cargo run`
## Как собрать в Linux
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### Установка vcpkg
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### Исправления libvpx (Для Fedora)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### Сборка
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
mv libsciter-gtk.so target/debug
VCPKG_ROOT=$HOME/vcpkg cargo run
```
### Смените Wayland на X11 (Xorg)
RustDesk не поддерживает Wayland. Смотрите [этот документ](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) для настройки Xorg в качестве сеанса GNOME по умолчанию.
## Как собрать используя Docker
Начните с клонирования репозитория и создания docker контейнера:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
Затем каждый раз, когда вам нужно собрать приложение, запустите следующую команду:
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
Обратите внимание, что первая сборка может занять больше времени но последующие сборки будут выполняться быстрее. Кроме того, если вам нужно указать другие аргументы для команды сборки, вы можете сделать это в конце команды в переменной `<OPTIONAL-ARGS>`. Например, если вы хотите создать оптимизированную версию, вы должны запустить приведенную выше команду и в хвосте строки добавить `---release`. Полученный исполняемый файл будет доступен в целевой папке вашей системы и может быть запущен с помощью:
```sh
target/debug/rustdesk
```
Или, если вы используете исполняемый файл релиза:
```sh
target/release/rustdesk
```
Пожалуйста, убедитесь, что вы запускаете эти команды из корня репозитория RustDesk, иначе приложение не сможет найти необходимые ресурсы. Также обратите внимание, что другие cargo подкоманды, такие как `install` или `run`, в настоящее время не поддерживаются этим методом, поскольку они будут устанавливать или запускать программу внутри контейнера, а не на хосте.
## Структура файлов
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: видеокодек, конфиг, обертка tcp/udp, protobuf, функции fs для передачи файлов и некоторые другие служебные функции
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: захват экрана
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: специфичное для платформы управление клавиатурой/мышью
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: графический пользовательский интерфейс
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: сервисы аудио/буфера обмена/ввода/видео и сетевых подключений
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: одноранговое соединение
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: свяжитесь с [rustdesk-server](https://github.com/rustdesk/rustdesk-server), дождитесь удаленного прямого (обход TCP NAT) или ретранслируемого соединения
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: специфичный для платформы код
## Снимки
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

214
README-ZH.md Normal file
View File

@@ -0,0 +1,214 @@
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Your remote desktop"><br>
<a href="#免费公共服务器">服务器</a> •
<a href="#基本构建步骤">编译</a> •
<a href="#使用Docker编译">Docker</a> •
<a href="#文件结构">结构</a> •
<a href="#截图">截图</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
</p>
Chat with us: [知乎](https://www.zhihu.com/people/rustdesk) | [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
远程桌面软件,开箱即用,无需任何配置。您完全掌控数据,不用担心安全问题。您可以使用我们的注册/中继服务器,
或者[自己设置](https://rustdesk.com/server)
亦或者[开发您的版本](https://github.com/rustdesk/rustdesk-server-demo)。
欢迎大家贡献代码, 请看 [`CONTRIBUTING.md`](CONTRIBUTING.md).
[**可执行程序下载**](https://github.com/rustdesk/rustdesk/releases)
## 免费公共服务器
以下是您免费使用的服务器,它可能会随着时间的推移而变化。如果您不靠近其中之一,您的网络可能会很慢。
- 首尔, AWS lightsail, 1 VCPU/0.5G RAM
- 新加坡, Vultr, 1 VCPU/1G RAM
- 达拉斯, Vultr, 1 VCPU/1G RAM
## 依赖
桌面版本界面使用[sciter](https://sciter.com/), 请自行下载。
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[macOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## 基本构建步骤
- 请准备好 Rust 开发环境和 C++编译环境
- 安装[vcpkg](https://github.com/microsoft/vcpkg), 正确设置`VCPKG_ROOT`环境变量
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/Osx: vcpkg install libvpx libyuv opus
- 运行 `cargo run`
## 在 Linux 上编译
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### 安装 vcpkg
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### 修复 libvpx (仅仅针对 Fedora)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### 构建
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
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 容器:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
针对国内网络访问问题,可以做以下几点优化:
1. Dockerfile 中修改系统的源到国内镜像
```
在Dockerfile的RUN apt update之前插入两行
RUN sed -i "s/deb.debian.org/mirrors.163.com/g" /etc/apt/sources.list
RUN sed -i "s/security.debian.org/mirrors.163.com/g" /etc/apt/sources.list
```
2. 修改容器系统中的 cargo 源,在`RUN ./rustup.sh -y`后插入下面代码:
```
RUN echo '[source.crates-io]' > ~/.cargo/config \
&& echo 'registry = "https://github.com/rust-lang/crates.io-index"' >> ~/.cargo/config \
&& echo '# 替换成你偏好的镜像源' >> ~/.cargo/config \
&& echo "replace-with = 'sjtu'" >> ~/.cargo/config \
&& echo '# 上海交通大学' >> ~/.cargo/config \
&& echo '[source.sjtu]' >> ~/.cargo/config \
&& echo 'registry = "https://mirrors.sjtug.sjtu.edu.cn/git/crates.io-index"' >> ~/.cargo/config \
&& echo '' >> ~/.cargo/config
```
3. Dockerfile 中加入代理的 env
```
在User root后插入两行
ENV http_proxy=http://host:port
ENV https_proxy=http://host:port
```
4. docker build 命令后面加上 proxy 参数
```
docker build -t "rustdesk-builder" . --build-arg http_proxy=http://host:port --build-arg https_proxy=http://host:port
```
然后,每次需要构建应用程序时,运行以下命令:
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
运行若遇到无权限问题,出现以下提示:
```
usermod: user user is currently used by process 1
groupmod: Permission denied.
groupmod: cannot lock /etc/group; try again later.
```
可以尝试把`-e PUID="$(id -u)" -e PGID="$(id -g)"`参数去掉。(出现这一问题的原因是容器中的 entrypoint 脚本中判定 uid 和 gid 与给定的环境变量不一致时会修改 user 的 uid 和 gid 重新运行,但是重新运行时取不到环境变量中的 uid 和 gid 了,会再次进入 uid 与 gid 与给定值不一致的逻辑分支)
请注意,第一次构建可能需要比较长的时间,因为需要缓存依赖项(国内网络经常出现拉取失败,可多尝试几次),后续构建会更快。此外,如果您需要为构建命令指定不同的参数,
您可以在命令末尾的 `<OPTIONAL-ARGS>` 位置执行此操作。例如,如果你想构建一个优化的发布版本,你可以在命令后跟 `---release`。
将在 target 下产生可执行程序,请通过以下方式运行调试版本:
```sh
target/debug/rustdesk
```
或者运行发布版本:
```sh
target/release/rustdesk
```
请确保您从 RustDesk 存储库的根目录运行这些命令,否则应用程序可能无法找到所需的资源。另请注意,此方法当前不支持其他`Cargo`子命令,
例如 `install` 或 `run`,因为运行在容器里,而不是宿主机上。
## 文件结构
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: 视频编解码, 配置, tcp/udp 封装, protobuf, 文件传输相关文件系统操作函数, 以及一些其他实用函数
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: 截屏
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: 平台相关的鼠标键盘输入
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: 被控端服务audio/clipboard/input/video 服务, 已经连接实现
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: 控制端
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: 与[rustdesk-server](https://github.com/rustdesk/rustdesk-server)保持 UDP 通讯, 等待远程连接(通过打洞直连或者中继)
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: 平台服务相关代码
## 截图
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

147
README.md
View File

@@ -1,27 +1,143 @@
# RustDesk | Your Remote Desktop Software
<p align="center">
<img src="logo-header.svg" alt="RustDesk - Your remote desktop"><br>
<a href="#free-public-servers">Servers</a> •
<a href="#raw-steps-to-build">Build</a> •
<a href="#how-to-build-with-docker">Docker</a> •
<a href="#file-structure">Structure</a> •
<a href="#snapshot">Snapshot</a><br>
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>]<br>
<b>We need your help to translate this README and <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang">RustDesk UI</a> to your native language</b>
</p>
The best open-source remote desktop software, written in Rust. Works out of the box, no configuration required. Great alternative to TeamViewer and AnyDesk! You have full control of your data, with no concerns about security. You can use our rendezvous/relay server, [set up your own](https://rustdesk.com/blog/id-relay-set/), or write your own rendezvous/relay server.
Chat with us: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I04VU09)
Yet another remote desktop software, written in Rust. Works out of the box, no configuration required. You have full control of your data, with no concerns about security. You can use our rendezvous/relay server, [set up your own](https://rustdesk.com/server), or [write your own rendezvous/relay server](https://github.com/rustdesk/rustdesk-server-demo).
RustDesk welcomes contribution from everyone. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for help getting started.
[**BINARY DOWNLOAD**](https://github.com/rustdesk/rustdesk/releases)
## Dependences
## Free Public Servers
Below are the servers you are using for free, it may change along the time. If you are not close to one of these, your network may be slow.
| Location | Vendor | Specification |
| --------- | ------------- | ------------------ |
| Seoul | AWS lightsail | 1 VCPU / 0.5GB RAM |
| Singapore | Vultr | 1 VCPU / 1GB RAM |
| Dallas | Vultr | 1 VCPU / 1GB RAM | |
## Dependencies
Desktop versions use [sciter](https://sciter.com/) for GUI, please download sciter dynamic library yourself.
[Windows](https://github.com/c-smile/sciter-sdk/blob/dc65744b66389cd5a0ff6bdb7c63a8b7b05a708b/bin.win/x64/sciter.dll)
[Linux](https://github.com/c-smile/sciter-sdk/raw/dc65744b66389cd5a0ff6bdb7c63a8b7b05a708b/bin.lnx/x64/libsciter-gtk.so)
[Osx](https://github.com/c-smile/sciter-sdk/raw/dc65744b66389cd5a0ff6bdb7c63a8b7b05a708b/bin.osx/sciter-osx-64.dylib)
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
## How To Build
## Raw steps to build
* Prepare your Rust development env and C++ build env
- Prepare your Rust development env and C++ build env
* Install [vcpkg](https://github.com/microsoft/vcpkg), and set `VCPKG_ROOT` env variable correctly
- Install [vcpkg](https://github.com/microsoft/vcpkg), and set `VCPKG_ROOT` env variable correctly
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/Osx: vcpkg install libvpx libyuv opus
* run `cargo run`
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- run `cargo run`
## How to build on Linux
### Ubuntu 18 (Debian 10)
```sh
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
```
### Fedora 28 (CentOS 8)
```sh
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
```
### Arch (Manjaro)
```sh
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
```
### Install vcpkg
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
```
### Fix libvpx (For Fedora)
```sh
cd vcpkg/buildtrees/libvpx/src
cd *
./configure
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
make
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
cd
```
### Build
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
mkdir -p target/debug
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
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:
```sh
git clone https://github.com/rustdesk/rustdesk
cd rustdesk
docker build -t "rustdesk-builder" .
```
Then, each time you need to build the application, run the following command:
```sh
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
```
Note that the first build may take longer before dependencies are cached, subsequent builds will be faster. Additionally, if you need to specify different arguments to the build command, you may do so at the end of the command in the `<OPTIONAL-ARGS>` position. For instance, if you wanted to build an optimized release version, you would run the command above followed by `---release`. The resulting executable will be available in the target folder on your system, and can be run with:
```sh
target/debug/rustdesk
```
Or, if you're running a release executable:
```sh
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.
## File Structure
@@ -35,12 +151,11 @@ Desktop versions use [sciter](https://sciter.com/) for GUI, please download scit
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: platform specific code
## Snapshot
![image](https://user-images.githubusercontent.com/71636191/113112362-ae4deb80-923b-11eb-957d-ff88daad4f06.png)
![image](https://user-images.githubusercontent.com/71636191/113112619-f705a480-923b-11eb-911d-97e984ef52b6.png)
![image](https://user-images.githubusercontent.com/71636191/113112857-3fbd5d80-923c-11eb-9836-768325faf906.png)
![image](https://user-images.githubusercontent.com/71636191/113112990-65e2fd80-923c-11eb-840e-349b4d6e340d.png)
![image](https://user-images.githubusercontent.com/71636191/135385039-38fdbd72-379a-422d-b97f-33df71fb1cec.png)

13
SECURITY.md Normal file
View File

@@ -0,0 +1,13 @@
# Security Policy
## Supported Versions
| Version | Supported |
| --------- | ------------------ |
| 1.1.x | :white_check_mark: |
| 1.x | :white_check_mark: |
| Below 1.0 | :x: |
## Reporting a Vulnerability
Here we should write what to do in case of a security vulnerability

112
build.py Normal file
View File

@@ -0,0 +1,112 @@
#!/usr/bin/env python3
import os
import platform
import zlib
from shutil import copy2
import hashlib
windows = platform.platform().startswith('Windows')
osx = platform.platform().startswith('Darwin') or platform.platform().startswith("macOS")
hbb_name = 'rustdesk' + ('.exe' if windows else '')
exe_path = 'target/release/' + hbb_name
def get_version():
with open("Cargo.toml") as fh:
for line in fh:
if line.startswith("version"):
return line.replace("version", "").replace("=", "").replace('"', '').strip()
return ''
def main():
os.system("cp Cargo.toml Cargo.toml.bk")
os.system("cp src/main.rs src/main.rs.bk")
if windows:
txt = open('src/main.rs', encoding='utf8').read()
with open('src/main.rs', 'wt', encoding='utf8') as fh:
fh.write(txt.replace(
'//#![windows_subsystem', '#![windows_subsystem'))
if os.path.exists(exe_path):
os.unlink(exe_path)
os.system('python3 inline-sciter.py')
if os.path.isfile('/usr/bin/pacman'):
os.system('git checkout src/ui/common.tis')
version = get_version()
if windows:
os.system('cargo build --release --features inline')
# os.system('upx.exe target/release/rustdesk.exe')
os.system('mv target/release/rustdesk.exe target/release/RustDesk.exe')
pa = os.environ.get('P')
if pa:
os.system('signtool sign /a /v /p %s /debug /f .\\cert.pfx /t http://timestamp.digicert.com target\\release\\rustdesk.exe'%pa)
else:
print('Not signed')
os.system('cp -rf target/release/RustDesk.exe rustdesk-%s-putes.exe'%version)
else:
os.system('cargo bundle --release --features inline')
if osx:
os.system(
'strip target/release/bundle/osx/RustDesk.app/Contents/MacOS/rustdesk')
os.system(
'cp libsciter.dylib target/release/bundle/osx/RustDesk.app/Contents/MacOS/')
# https://github.com/sindresorhus/create-dmg
os.system('/bin/rm -rf *.dmg')
plist = "target/release/bundle/osx/RustDesk.app/Contents/Info.plist"
txt = open(plist).read()
with open(plist, "wt") as fh:
fh.write(txt.replace("</dict>", """
<key>LSUIElement</key>
<string>1</string>
</dict>"""))
pa = os.environ.get('P')
if pa:
os.system('''
# buggy: rcodesign sign ... path/*, have to sign one by one
#rcodesign sign --p12-file ~/.p12/rustdesk-developer-id.p12 --p12-password-file ~/.p12/.cert-pass --code-signature-flags runtime ./target/release/bundle/osx/RustDesk.app/Contents/MacOS/rustdesk
#rcodesign sign --p12-file ~/.p12/rustdesk-developer-id.p12 --p12-password-file ~/.p12/.cert-pass --code-signature-flags runtime ./target/release/bundle/osx/RustDesk.app/Contents/MacOS/libsciter.dylib
#rcodesign sign --p12-file ~/.p12/rustdesk-developer-id.p12 --p12-password-file ~/.p12/.cert-pass --code-signature-flags runtime ./target/release/bundle/osx/RustDesk.app
# goto "Keychain Access" -> "My Certificates" for below id which starts with "Developer ID Application:"
codesign -s "Developer ID Application: {0}" --force --options runtime ./target/release/bundle/osx/RustDesk.app/Contents/MacOS/*
codesign -s "Developer ID Application: {0}" --force --options runtime ./target/release/bundle/osx/RustDesk.app
'''.format(pa))
os.system('create-dmg target/release/bundle/osx/RustDesk.app')
os.rename('RustDesk %s.dmg'%version, 'rustdesk-%s.dmg'%version)
if pa:
os.system('''
#rcodesign sign --p12-file ~/.p12/rustdesk-developer-id.p12 --p12-password-file ~/.p12/.cert-pass --code-signature-flags runtime ./rustdesk-{1}.dmg
codesign -s "Developer ID Application: {0}" --force --options runtime ./rustdesk-{1}.dmg
# https://pyoxidizer.readthedocs.io/en/latest/apple_codesign_rcodesign.html
rcodesign notarize --api-issuer 69a6de7d-2907-47e3-e053-5b8c7c11a4d1 --api-key 9JBRHG3JHT --staple ./rustdesk-{1}.dmg
# verify: spctl -a -t exec -v /Applications/RustDesk.app
'''.format(pa, version))
else:
print('Not signed')
else:
os.system('mv target/release/bundle/deb/rustdesk*.deb ./rustdesk.deb')
os.system('dpkg-deb -R rustdesk.deb tmpdeb')
os.system('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/')
os.system(
'cp rustdesk.service tmpdeb/usr/share/rustdesk/files/systemd/')
os.system('cp pynput_service.py tmpdeb/usr/share/rustdesk/files/')
os.system('cp DEBIAN/* tmpdeb/DEBIAN/')
os.system('strip tmpdeb/usr/bin/rustdesk')
os.system('mkdir -p tmpdeb/usr/lib/rustdesk')
os.system('cp libsciter-gtk.so tmpdeb/usr/lib/rustdesk/')
md5_file('usr/share/rustdesk/files/systemd/rustdesk.service')
md5_file('usr/share/rustdesk/files/pynput_service.py')
md5_file('usr/lib/rustdesk/libsciter-gtk.so')
os.system('dpkg-deb -b tmpdeb rustdesk.deb; /bin/rm -rf tmpdeb/')
os.rename('rustdesk.deb', 'rustdesk-%s.deb'%version)
os.system("mv Cargo.toml.bk Cargo.toml")
os.system("mv src/main.rs.bk src/main.rs")
def md5_file(fn):
md5 = hashlib.md5(open('tmpdeb/' + fn, 'rb').read()).hexdigest()
os.system('echo "%s %s" >> tmpdeb/DEBIAN/md5sums' % (md5, fn))
if __name__ == "__main__":
main()

34
entrypoint Executable file
View File

@@ -0,0 +1,34 @@
#!/bin/sh
cd $HOME/rustdesk
. $HOME/.cargo/env
argv=$@
while test $# -gt 0; do
case "$1" in
--release)
mkdir -p target/release
test -f target/release/libsciter-gtk.so || cp $HOME/libsciter-gtk.so target/release/
release=1
shift
;;
--target)
shift
if test $# -gt 0; then
rustup target add $1
shift
fi
;;
*)
shift
;;
esac
done
if [ -z $release ]; then
mkdir -p target/debug
test -f target/debug/libsciter-gtk.so || cp $HOME/libsciter-gtk.so target/debug/
fi
VCPKG_ROOT=/vcpkg cargo build $argv

81
inline-sciter.py Normal file
View File

@@ -0,0 +1,81 @@
#!/usr/bin/env python3
import re
def strip(s): return re.sub(r'\s+\n', '\n', re.sub(r'\n\s+', '\n', s))
common_css = open('src/ui/common.css').read()
common_tis = open('src/ui/common.tis', encoding='UTF8').read()
index = open('src/ui/index.html').read() \
.replace('@import url(index.css);', open('src/ui/index.css').read()) \
.replace('include "index.tis";', open('src/ui/index.tis').read()) \
.replace('include "msgbox.tis";', open('src/ui/msgbox.tis').read()) \
.replace('include "ab.tis";', open('src/ui/ab.tis').read())
remote = open('src/ui/remote.html').read() \
.replace('@import url(remote.css);', open('src/ui/remote.css').read()) \
.replace('@import url(header.css);', open('src/ui/header.css').read()) \
.replace('@import url(file_transfer.css);', open('src/ui/file_transfer.css').read()) \
.replace('include "remote.tis";', open('src/ui/remote.tis').read()) \
.replace('include "msgbox.tis";', open('src/ui/msgbox.tis').read()) \
.replace('include "grid.tis";', open('src/ui/grid.tis').read()) \
.replace('include "header.tis";', open('src/ui/header.tis').read()) \
.replace('include "file_transfer.tis";', open('src/ui/file_transfer.tis').read()) \
.replace('include "port_forward.tis";', open('src/ui/port_forward.tis').read())
chatbox = open('src/ui/chatbox.html').read()
install = open('src/ui/install.html').read().replace('include "install.tis";', open('src/ui/install.tis').read())
cm = open('src/ui/cm.html').read() \
.replace('@import url(cm.css);', open('src/ui/cm.css').read()) \
.replace('include "cm.tis";', open('src/ui/cm.tis').read())
def compress(s):
s = s.replace("\r\n", "\n")
x = bytes(s, encoding='utf-8')
return '&[u8; ' + str(len(x)) + '] = b"' + str(x)[2:-1].replace(r"\'", "'").replace(r'"',
r'\"') + '"'
with open('src/ui/inline.rs', 'wt') as fh:
fh.write('const _COMMON_CSS: ' + compress(strip(common_css)) + ';\n')
fh.write('const _COMMON_TIS: ' + compress(strip(common_tis)) + ';\n')
fh.write('const _INDEX: ' + compress(strip(index)) + ';\n')
fh.write('const _REMOTE: ' + compress(strip(remote)) + ';\n')
fh.write('const _CHATBOX: ' + compress(strip(chatbox)) + ';\n')
fh.write('const _INSTALL: ' + compress(strip(install)) + ';\n')
fh.write('const _CONNECTION_MANAGER: ' + compress(strip(cm)) + ';\n')
fh.write('''
fn get(data: &[u8]) -> String {
String::from_utf8_lossy(data).to_string()
}
fn replace(data: &[u8]) -> String {
let css = get(&_COMMON_CSS[..]);
let res = get(data).replace("@import url(common.css);", &css);
let tis = get(&_COMMON_TIS[..]);
res.replace("include \\\"common.tis\\\";", &tis)
}
#[inline]
pub fn get_index() -> String {
replace(&_INDEX[..])
}
#[inline]
pub fn get_remote() -> String {
replace(&_REMOTE[..])
}
#[inline]
pub fn get_install() -> String {
replace(&_INSTALL[..])
}
#[inline]
pub fn get_chatbox() -> String {
replace(&_CHATBOX[..])
}
#[inline]
pub fn get_cm() -> String {
replace(&_CONNECTION_MANAGER[..])
}
''')

17
libs/clipboard/Cargo.toml Normal file
View File

@@ -0,0 +1,17 @@
[package]
name = "clipboard"
version = "0.1.0"
edition = "2021"
build= "build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
cc = "1.0"
[dependencies]
thiserror = "1.0.30"
lazy_static = "1.4"
serde = "1.0"
serde_derive = "1.0"
hbb_common = { path = "../hbb_common" }

16
libs/clipboard/README.md Normal file
View File

@@ -0,0 +1,16 @@
# clipboard
Copy files and text through network.
Main lowlevel logic from [FreeRDP](https://github.com/FreeRDP/FreeRDP).
TODO: Move this lib to a separate project.
## impl
### windows
![scene](./docs/assets/scene3.png)
![A1->B1](./docs/assets/win_A_B.png)
![B1->A1](./docs/assets/win_B_A.png)

43
libs/clipboard/build.rs Normal file
View File

@@ -0,0 +1,43 @@
use cc;
fn build_c_impl() {
let mut build = cc::Build::new();
#[cfg(target_os = "windows")]
build.file("src/windows/wf_cliprdr.c");
#[cfg(target_os = "linux")]
build.file("src/X11/xf_cliprdr.c");
#[cfg(target_os = "macos")]
build.file("src/OSX/Clipboard.m");
build.flag_if_supported("-Wno-c++0x-extensions");
build.flag_if_supported("-Wno-return-type-c-linkage");
build.flag_if_supported("-Wno-invalid-offsetof");
build.flag_if_supported("-Wno-unused-parameter");
if build.get_compiler().is_like_msvc() {
build.define("WIN32", "");
// build.define("_AMD64_", "");
build.flag("-Zi");
build.flag("-GR-");
// build.flag("-std:c++11");
} else {
build.flag("-fPIC");
// build.flag("-std=c++11");
// build.flag("-include");
// build.flag(&confdefs_path.to_string_lossy());
}
build.compile("mycliprdr");
#[cfg(target_os = "windows")]
println!("cargo:rerun-if-changed=src/windows/wf_cliprdr.c");
#[cfg(target_os = "linux")]
println!("cargo:rerun-if-changed=src/X11/xf_cliprdr.c");
#[cfg(target_os = "macos")]
println!("cargo:rerun-if-changed=src/OSX/Clipboard.m");
}
fn main() {
build_c_impl();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View File

@@ -0,0 +1,11 @@
#include "../cliprdr.h"
void mac_cliprdr_init(CliprdrClientContext *cliprdr)
{
(void)cliprdr;
}
void mac_cliprdr_uninit(CliprdrClientContext *cliprdr)
{
(void)cliprdr;
}

View File

@@ -0,0 +1,11 @@
#include "../cliprdr.h"
void xf_cliprdr_init(CliprdrClientContext* cliprdr)
{
(void)cliprdr;
}
void xf_cliprdr_uninit( CliprdrClientContext* cliprdr)
{
(void)cliprdr;
}

View File

@@ -0,0 +1,233 @@
#ifndef WF_CLIPRDR_H__
#define WF_CLIPRDR_H__
#ifdef __cplusplus
extern "C"
{
#endif
typedef signed char INT8, *PINT8;
typedef signed short INT16, *PINT16;
typedef signed int INT32, *PINT32;
typedef unsigned char UINT8, *PUINT8;
typedef unsigned short UINT16, *PUINT16;
typedef unsigned int UINT32, *PUINT32;
typedef unsigned int UINT;
typedef int BOOL;
typedef unsigned char BYTE;
/* Clipboard Messages */
#define DEFINE_CLIPRDR_HEADER_COMMON() \
UINT32 connID; \
UINT16 msgType; \
UINT16 msgFlags; \
UINT32 dataLen
struct _CLIPRDR_HEADER
{
DEFINE_CLIPRDR_HEADER_COMMON();
};
typedef struct _CLIPRDR_HEADER CLIPRDR_HEADER;
struct _CLIPRDR_CAPABILITY_SET
{
UINT16 capabilitySetType;
UINT16 capabilitySetLength;
};
typedef struct _CLIPRDR_CAPABILITY_SET CLIPRDR_CAPABILITY_SET;
struct _CLIPRDR_GENERAL_CAPABILITY_SET
{
UINT16 capabilitySetType;
UINT16 capabilitySetLength;
UINT32 version;
UINT32 generalFlags;
};
typedef struct _CLIPRDR_GENERAL_CAPABILITY_SET CLIPRDR_GENERAL_CAPABILITY_SET;
struct _CLIPRDR_CAPABILITIES
{
DEFINE_CLIPRDR_HEADER_COMMON();
UINT32 cCapabilitiesSets;
CLIPRDR_CAPABILITY_SET *capabilitySets;
};
typedef struct _CLIPRDR_CAPABILITIES CLIPRDR_CAPABILITIES;
struct _CLIPRDR_MONITOR_READY
{
DEFINE_CLIPRDR_HEADER_COMMON();
};
typedef struct _CLIPRDR_MONITOR_READY CLIPRDR_MONITOR_READY;
struct _CLIPRDR_TEMP_DIRECTORY
{
DEFINE_CLIPRDR_HEADER_COMMON();
char szTempDir[520];
};
typedef struct _CLIPRDR_TEMP_DIRECTORY CLIPRDR_TEMP_DIRECTORY;
struct _CLIPRDR_FORMAT
{
UINT32 formatId;
char *formatName;
};
typedef struct _CLIPRDR_FORMAT CLIPRDR_FORMAT;
struct _CLIPRDR_FORMAT_LIST
{
DEFINE_CLIPRDR_HEADER_COMMON();
UINT32 numFormats;
CLIPRDR_FORMAT *formats;
};
typedef struct _CLIPRDR_FORMAT_LIST CLIPRDR_FORMAT_LIST;
struct _CLIPRDR_FORMAT_LIST_RESPONSE
{
DEFINE_CLIPRDR_HEADER_COMMON();
};
typedef struct _CLIPRDR_FORMAT_LIST_RESPONSE CLIPRDR_FORMAT_LIST_RESPONSE;
struct _CLIPRDR_LOCK_CLIPBOARD_DATA
{
DEFINE_CLIPRDR_HEADER_COMMON();
UINT32 clipDataId;
};
typedef struct _CLIPRDR_LOCK_CLIPBOARD_DATA CLIPRDR_LOCK_CLIPBOARD_DATA;
struct _CLIPRDR_UNLOCK_CLIPBOARD_DATA
{
DEFINE_CLIPRDR_HEADER_COMMON();
UINT32 clipDataId;
};
typedef struct _CLIPRDR_UNLOCK_CLIPBOARD_DATA CLIPRDR_UNLOCK_CLIPBOARD_DATA;
struct _CLIPRDR_FORMAT_DATA_REQUEST
{
DEFINE_CLIPRDR_HEADER_COMMON();
UINT32 requestedFormatId;
};
typedef struct _CLIPRDR_FORMAT_DATA_REQUEST CLIPRDR_FORMAT_DATA_REQUEST;
struct _CLIPRDR_FORMAT_DATA_RESPONSE
{
DEFINE_CLIPRDR_HEADER_COMMON();
const BYTE *requestedFormatData;
};
typedef struct _CLIPRDR_FORMAT_DATA_RESPONSE CLIPRDR_FORMAT_DATA_RESPONSE;
struct _CLIPRDR_FILE_CONTENTS_REQUEST
{
DEFINE_CLIPRDR_HEADER_COMMON();
UINT32 streamId;
UINT32 listIndex;
UINT32 dwFlags;
UINT32 nPositionLow;
UINT32 nPositionHigh;
UINT32 cbRequested;
BOOL haveClipDataId;
UINT32 clipDataId;
};
typedef struct _CLIPRDR_FILE_CONTENTS_REQUEST CLIPRDR_FILE_CONTENTS_REQUEST;
struct _CLIPRDR_FILE_CONTENTS_RESPONSE
{
DEFINE_CLIPRDR_HEADER_COMMON();
UINT32 streamId;
UINT32 cbRequested;
const BYTE *requestedData;
};
typedef struct _CLIPRDR_FILE_CONTENTS_RESPONSE CLIPRDR_FILE_CONTENTS_RESPONSE;
typedef struct _cliprdr_client_context CliprdrClientContext;
typedef UINT (*pcCliprdrServerCapabilities)(CliprdrClientContext *context,
const CLIPRDR_CAPABILITIES *capabilities);
typedef UINT (*pcCliprdrClientCapabilities)(CliprdrClientContext *context,
const CLIPRDR_CAPABILITIES *capabilities);
typedef UINT (*pcCliprdrMonitorReady)(CliprdrClientContext *context,
const CLIPRDR_MONITOR_READY *monitorReady);
typedef UINT (*pcCliprdrTempDirectory)(CliprdrClientContext *context,
const CLIPRDR_TEMP_DIRECTORY *tempDirectory);
typedef UINT (*pcCliprdrClientFormatList)(CliprdrClientContext *context,
const CLIPRDR_FORMAT_LIST *formatList);
typedef UINT (*pcCliprdrServerFormatList)(CliprdrClientContext *context,
const CLIPRDR_FORMAT_LIST *formatList);
typedef UINT (*pcCliprdrClientFormatListResponse)(
CliprdrClientContext *context, const CLIPRDR_FORMAT_LIST_RESPONSE *formatListResponse);
typedef UINT (*pcCliprdrServerFormatListResponse)(
CliprdrClientContext *context, const CLIPRDR_FORMAT_LIST_RESPONSE *formatListResponse);
typedef UINT (*pcCliprdrClientLockClipboardData)(
CliprdrClientContext *context, const CLIPRDR_LOCK_CLIPBOARD_DATA *lockClipboardData);
typedef UINT (*pcCliprdrServerLockClipboardData)(
CliprdrClientContext *context, const CLIPRDR_LOCK_CLIPBOARD_DATA *lockClipboardData);
typedef UINT (*pcCliprdrClientUnlockClipboardData)(
CliprdrClientContext *context, const CLIPRDR_UNLOCK_CLIPBOARD_DATA *unlockClipboardData);
typedef UINT (*pcCliprdrServerUnlockClipboardData)(
CliprdrClientContext *context, const CLIPRDR_UNLOCK_CLIPBOARD_DATA *unlockClipboardData);
typedef UINT (*pcCliprdrClientFormatDataRequest)(
CliprdrClientContext *context, const CLIPRDR_FORMAT_DATA_REQUEST *formatDataRequest);
typedef UINT (*pcCliprdrServerFormatDataRequest)(
CliprdrClientContext *context, const CLIPRDR_FORMAT_DATA_REQUEST *formatDataRequest);
typedef UINT (*pcCliprdrClientFormatDataResponse)(
CliprdrClientContext *context, const CLIPRDR_FORMAT_DATA_RESPONSE *formatDataResponse);
typedef UINT (*pcCliprdrServerFormatDataResponse)(
CliprdrClientContext *context, const CLIPRDR_FORMAT_DATA_RESPONSE *formatDataResponse);
typedef UINT (*pcCliprdrClientFileContentsRequest)(
CliprdrClientContext *context, const CLIPRDR_FILE_CONTENTS_REQUEST *fileContentsRequest);
typedef UINT (*pcCliprdrServerFileContentsRequest)(
CliprdrClientContext *context, const CLIPRDR_FILE_CONTENTS_REQUEST *fileContentsRequest);
typedef UINT (*pcCliprdrClientFileContentsResponse)(
CliprdrClientContext *context, const CLIPRDR_FILE_CONTENTS_RESPONSE *fileContentsResponse);
typedef UINT (*pcCliprdrServerFileContentsResponse)(
CliprdrClientContext *context, const CLIPRDR_FILE_CONTENTS_RESPONSE *fileContentsResponse);
typedef BOOL (*pcCheckEnabled)(UINT32 connID);
// TODO: hide more members of clipboard context
struct _cliprdr_client_context
{
void *custom;
BOOL enableFiles;
BOOL enableOthers;
pcCheckEnabled CheckEnabled;
pcCliprdrServerCapabilities ServerCapabilities;
pcCliprdrClientCapabilities ClientCapabilities;
pcCliprdrMonitorReady MonitorReady;
pcCliprdrTempDirectory TempDirectory;
pcCliprdrClientFormatList ClientFormatList;
pcCliprdrServerFormatList ServerFormatList;
pcCliprdrClientFormatListResponse ClientFormatListResponse;
pcCliprdrServerFormatListResponse ServerFormatListResponse;
pcCliprdrClientLockClipboardData ClientLockClipboardData;
pcCliprdrServerLockClipboardData ServerLockClipboardData;
pcCliprdrClientUnlockClipboardData ClientUnlockClipboardData;
pcCliprdrServerUnlockClipboardData ServerUnlockClipboardData;
pcCliprdrClientFormatDataRequest ClientFormatDataRequest;
pcCliprdrServerFormatDataRequest ServerFormatDataRequest;
pcCliprdrClientFormatDataResponse ClientFormatDataResponse;
pcCliprdrServerFormatDataResponse ServerFormatDataResponse;
pcCliprdrClientFileContentsRequest ClientFileContentsRequest;
pcCliprdrServerFileContentsRequest ServerFileContentsRequest;
pcCliprdrClientFileContentsResponse ClientFileContentsResponse;
pcCliprdrServerFileContentsResponse ServerFileContentsResponse;
UINT32 lastRequestedFormatId;
};
#ifdef __cplusplus
}
#endif
#endif // WF_CLIPRDR_H__

View File

@@ -0,0 +1,564 @@
#![allow(dead_code)]
#![allow(non_camel_case_types)]
#![allow(unused_variables)]
#![allow(non_snake_case)]
#![allow(deref_nullptr)]
use std::{boxed::Box, result::Result};
use thiserror::Error;
pub type size_t = ::std::os::raw::c_ulonglong;
pub type __vcrt_bool = bool;
pub type wchar_t = ::std::os::raw::c_ushort;
pub type POINTER_64_INT = ::std::os::raw::c_ulonglong;
pub type INT8 = ::std::os::raw::c_schar;
pub type PINT8 = *mut ::std::os::raw::c_schar;
pub type INT16 = ::std::os::raw::c_short;
pub type PINT16 = *mut ::std::os::raw::c_short;
pub type INT32 = ::std::os::raw::c_int;
pub type PINT32 = *mut ::std::os::raw::c_int;
pub type INT64 = ::std::os::raw::c_longlong;
pub type PINT64 = *mut ::std::os::raw::c_longlong;
pub type UINT8 = ::std::os::raw::c_uchar;
pub type PUINT8 = *mut ::std::os::raw::c_uchar;
pub type UINT16 = ::std::os::raw::c_ushort;
pub type PUINT16 = *mut ::std::os::raw::c_ushort;
pub type UINT32 = ::std::os::raw::c_uint;
pub type PUINT32 = *mut ::std::os::raw::c_uint;
pub type UINT64 = ::std::os::raw::c_ulonglong;
pub type PUINT64 = *mut ::std::os::raw::c_ulonglong;
pub type LONG32 = ::std::os::raw::c_int;
pub type PLONG32 = *mut ::std::os::raw::c_int;
pub type ULONG32 = ::std::os::raw::c_uint;
pub type PULONG32 = *mut ::std::os::raw::c_uint;
pub type DWORD32 = ::std::os::raw::c_uint;
pub type PDWORD32 = *mut ::std::os::raw::c_uint;
pub type INT_PTR = ::std::os::raw::c_longlong;
pub type PINT_PTR = *mut ::std::os::raw::c_longlong;
pub type UINT_PTR = ::std::os::raw::c_ulonglong;
pub type PUINT_PTR = *mut ::std::os::raw::c_ulonglong;
pub type LONG_PTR = ::std::os::raw::c_longlong;
pub type PLONG_PTR = *mut ::std::os::raw::c_longlong;
pub type ULONG_PTR = ::std::os::raw::c_ulonglong;
pub type PULONG_PTR = *mut ::std::os::raw::c_ulonglong;
pub type SHANDLE_PTR = ::std::os::raw::c_longlong;
pub type HANDLE_PTR = ::std::os::raw::c_ulonglong;
pub type UHALF_PTR = ::std::os::raw::c_uint;
pub type PUHALF_PTR = *mut ::std::os::raw::c_uint;
pub type HALF_PTR = ::std::os::raw::c_int;
pub type PHALF_PTR = *mut ::std::os::raw::c_int;
pub type SIZE_T = ULONG_PTR;
pub type PSIZE_T = *mut ULONG_PTR;
pub type SSIZE_T = LONG_PTR;
pub type PSSIZE_T = *mut LONG_PTR;
pub type DWORD_PTR = ULONG_PTR;
pub type PDWORD_PTR = *mut ULONG_PTR;
pub type LONG64 = ::std::os::raw::c_longlong;
pub type PLONG64 = *mut ::std::os::raw::c_longlong;
pub type ULONG64 = ::std::os::raw::c_ulonglong;
pub type PULONG64 = *mut ::std::os::raw::c_ulonglong;
pub type DWORD64 = ::std::os::raw::c_ulonglong;
pub type PDWORD64 = *mut ::std::os::raw::c_ulonglong;
pub type KAFFINITY = ULONG_PTR;
pub type PKAFFINITY = *mut KAFFINITY;
pub type PVOID = *mut ::std::os::raw::c_void;
pub type CHAR = ::std::os::raw::c_char;
pub type SHORT = ::std::os::raw::c_short;
pub type LONG = ::std::os::raw::c_long;
pub type WCHAR = wchar_t;
pub type PWCHAR = *mut WCHAR;
pub type LPWCH = *mut WCHAR;
pub type PWCH = *mut WCHAR;
pub type LPCWCH = *const WCHAR;
pub type PCWCH = *const WCHAR;
pub type NWPSTR = *mut WCHAR;
pub type LPWSTR = *mut WCHAR;
pub type PWSTR = *mut WCHAR;
pub type PZPWSTR = *mut PWSTR;
pub type PCZPWSTR = *const PWSTR;
pub type LPUWSTR = *mut WCHAR;
pub type PUWSTR = *mut WCHAR;
pub type LPCWSTR = *const WCHAR;
pub type PCWSTR = *const WCHAR;
pub type PZPCWSTR = *mut PCWSTR;
pub type PCZPCWSTR = *const PCWSTR;
pub type LPCUWSTR = *const WCHAR;
pub type PCUWSTR = *const WCHAR;
pub type PZZWSTR = *mut WCHAR;
pub type PCZZWSTR = *const WCHAR;
pub type PUZZWSTR = *mut WCHAR;
pub type PCUZZWSTR = *const WCHAR;
pub type PNZWCH = *mut WCHAR;
pub type PCNZWCH = *const WCHAR;
pub type PUNZWCH = *mut WCHAR;
pub type PCUNZWCH = *const WCHAR;
pub type PCHAR = *mut CHAR;
pub type LPCH = *mut CHAR;
pub type PCH = *mut CHAR;
pub type LPCCH = *const CHAR;
pub type PCCH = *const CHAR;
pub type NPSTR = *mut CHAR;
pub type LPSTR = *mut CHAR;
pub type PSTR = *mut CHAR;
pub type PZPSTR = *mut PSTR;
pub type PCZPSTR = *const PSTR;
pub type LPCSTR = *const CHAR;
pub type PCSTR = *const CHAR;
pub type PZPCSTR = *mut PCSTR;
pub type PCZPCSTR = *const PCSTR;
pub type PZZSTR = *mut CHAR;
pub type PCZZSTR = *const CHAR;
pub type PNZCH = *mut CHAR;
pub type PCNZCH = *const CHAR;
pub type TCHAR = ::std::os::raw::c_char;
pub type PTCHAR = *mut ::std::os::raw::c_char;
pub type TBYTE = ::std::os::raw::c_uchar;
pub type PTBYTE = *mut ::std::os::raw::c_uchar;
pub type LPTCH = LPCH;
pub type PTCH = LPCH;
pub type LPCTCH = LPCCH;
pub type PCTCH = LPCCH;
pub type PTSTR = LPSTR;
pub type LPTSTR = LPSTR;
pub type PUTSTR = LPSTR;
pub type LPUTSTR = LPSTR;
pub type PCTSTR = LPCSTR;
pub type LPCTSTR = LPCSTR;
pub type PCUTSTR = LPCSTR;
pub type LPCUTSTR = LPCSTR;
pub type PZZTSTR = PZZSTR;
pub type PUZZTSTR = PZZSTR;
pub type PCZZTSTR = PCZZSTR;
pub type PCUZZTSTR = PCZZSTR;
pub type PZPTSTR = PZPSTR;
pub type PNZTCH = PNZCH;
pub type PUNZTCH = PNZCH;
pub type PCNZTCH = PCNZCH;
pub type PCUNZTCH = PCNZCH;
pub type PSHORT = *mut SHORT;
pub type PLONG = *mut LONG;
pub type ULONG = ::std::os::raw::c_ulong;
pub type PULONG = *mut ULONG;
pub type USHORT = ::std::os::raw::c_ushort;
pub type PUSHORT = *mut USHORT;
pub type UCHAR = ::std::os::raw::c_uchar;
pub type PUCHAR = *mut UCHAR;
pub type PSZ = *mut ::std::os::raw::c_char;
pub type DWORD = ::std::os::raw::c_ulong;
pub type BOOL = ::std::os::raw::c_int;
pub type BYTE = ::std::os::raw::c_uchar;
pub type WORD = ::std::os::raw::c_ushort;
pub type FLOAT = f32;
pub type PFLOAT = *mut FLOAT;
pub type PBOOL = *mut BOOL;
pub type LPBOOL = *mut BOOL;
pub type PBYTE = *mut BYTE;
pub type LPBYTE = *mut BYTE;
pub type PINT = *mut ::std::os::raw::c_int;
pub type LPINT = *mut ::std::os::raw::c_int;
pub type PWORD = *mut WORD;
pub type LPWORD = *mut WORD;
pub type LPLONG = *mut ::std::os::raw::c_long;
pub type PDWORD = *mut DWORD;
pub type LPDWORD = *mut DWORD;
pub type LPVOID = *mut ::std::os::raw::c_void;
pub type LPCVOID = *const ::std::os::raw::c_void;
pub type INT = ::std::os::raw::c_int;
pub type UINT = ::std::os::raw::c_uint;
pub type PUINT = *mut ::std::os::raw::c_uint;
pub type va_list = *mut ::std::os::raw::c_char;
pub const TRUE: ::std::os::raw::c_int = 1;
pub const FALSE: ::std::os::raw::c_int = 0;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_HEADER {
pub connID: UINT32,
pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
}
pub type CLIPRDR_HEADER = _CLIPRDR_HEADER;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_CAPABILITY_SET {
pub capabilitySetType: UINT16,
pub capabilitySetLength: UINT16,
}
pub type CLIPRDR_CAPABILITY_SET = _CLIPRDR_CAPABILITY_SET;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_GENERAL_CAPABILITY_SET {
pub capabilitySetType: UINT16,
pub capabilitySetLength: UINT16,
pub version: UINT32,
pub generalFlags: UINT32,
}
pub type CLIPRDR_GENERAL_CAPABILITY_SET = _CLIPRDR_GENERAL_CAPABILITY_SET;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_CAPABILITIES {
pub connID: UINT32,
pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
pub cCapabilitiesSets: UINT32,
pub capabilitySets: *mut CLIPRDR_CAPABILITY_SET,
}
pub type CLIPRDR_CAPABILITIES = _CLIPRDR_CAPABILITIES;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_MONITOR_READY {
pub connID: UINT32,
pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
}
pub type CLIPRDR_MONITOR_READY = _CLIPRDR_MONITOR_READY;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_TEMP_DIRECTORY {
pub connID: UINT32,
pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
pub szTempDir: [::std::os::raw::c_char; 520usize],
}
pub type CLIPRDR_TEMP_DIRECTORY = _CLIPRDR_TEMP_DIRECTORY;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_FORMAT {
pub formatId: UINT32,
pub formatName: *mut ::std::os::raw::c_char,
}
pub type CLIPRDR_FORMAT = _CLIPRDR_FORMAT;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_FORMAT_LIST {
pub connID: UINT32,
pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
pub numFormats: UINT32,
pub formats: *mut CLIPRDR_FORMAT,
}
pub type CLIPRDR_FORMAT_LIST = _CLIPRDR_FORMAT_LIST;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_FORMAT_LIST_RESPONSE {
pub connID: UINT32,
pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
}
pub type CLIPRDR_FORMAT_LIST_RESPONSE = _CLIPRDR_FORMAT_LIST_RESPONSE;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_LOCK_CLIPBOARD_DATA {
pub connID: UINT32,
pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
pub clipDataId: UINT32,
}
pub type CLIPRDR_LOCK_CLIPBOARD_DATA = _CLIPRDR_LOCK_CLIPBOARD_DATA;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_UNLOCK_CLIPBOARD_DATA {
pub connID: UINT32,
pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
pub clipDataId: UINT32,
}
pub type CLIPRDR_UNLOCK_CLIPBOARD_DATA = _CLIPRDR_UNLOCK_CLIPBOARD_DATA;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_FORMAT_DATA_REQUEST {
pub connID: UINT32,
pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
pub requestedFormatId: UINT32,
}
pub type CLIPRDR_FORMAT_DATA_REQUEST = _CLIPRDR_FORMAT_DATA_REQUEST;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_FORMAT_DATA_RESPONSE {
pub connID: UINT32,
pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
pub requestedFormatData: *const BYTE,
}
pub type CLIPRDR_FORMAT_DATA_RESPONSE = _CLIPRDR_FORMAT_DATA_RESPONSE;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_FILE_CONTENTS_REQUEST {
pub connID: UINT32,
pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
pub streamId: UINT32,
pub listIndex: UINT32,
pub dwFlags: UINT32,
pub nPositionLow: UINT32,
pub nPositionHigh: UINT32,
pub cbRequested: UINT32,
pub haveClipDataId: BOOL,
pub clipDataId: UINT32,
}
pub type CLIPRDR_FILE_CONTENTS_REQUEST = _CLIPRDR_FILE_CONTENTS_REQUEST;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _CLIPRDR_FILE_CONTENTS_RESPONSE {
pub connID: UINT32,
pub msgType: UINT16,
pub msgFlags: UINT16,
pub dataLen: UINT32,
pub streamId: UINT32,
pub cbRequested: UINT32,
pub requestedData: *const BYTE,
}
pub type CLIPRDR_FILE_CONTENTS_RESPONSE = _CLIPRDR_FILE_CONTENTS_RESPONSE;
pub type CliprdrClientContext = _cliprdr_client_context;
pub type pcCliprdrServerCapabilities = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
capabilities: *const CLIPRDR_CAPABILITIES,
) -> UINT,
>;
pub type pcCliprdrClientCapabilities = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
capabilities: *const CLIPRDR_CAPABILITIES,
) -> UINT,
>;
pub type pcCliprdrMonitorReady = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
monitorReady: *const CLIPRDR_MONITOR_READY,
) -> UINT,
>;
pub type pcCliprdrTempDirectory = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
tempDirectory: *const CLIPRDR_TEMP_DIRECTORY,
) -> UINT,
>;
pub type pcCliprdrClientFormatList = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
formatList: *const CLIPRDR_FORMAT_LIST,
) -> UINT,
>;
pub type pcCliprdrServerFormatList = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
formatList: *const CLIPRDR_FORMAT_LIST,
) -> UINT,
>;
pub type pcCliprdrClientFormatListResponse = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
formatListResponse: *const CLIPRDR_FORMAT_LIST_RESPONSE,
) -> UINT,
>;
pub type pcCliprdrServerFormatListResponse = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
formatListResponse: *const CLIPRDR_FORMAT_LIST_RESPONSE,
) -> UINT,
>;
pub type pcCliprdrClientLockClipboardData = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
lockClipboardData: *const CLIPRDR_LOCK_CLIPBOARD_DATA,
) -> UINT,
>;
pub type pcCliprdrServerLockClipboardData = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
lockClipboardData: *const CLIPRDR_LOCK_CLIPBOARD_DATA,
) -> UINT,
>;
pub type pcCliprdrClientUnlockClipboardData = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
unlockClipboardData: *const CLIPRDR_UNLOCK_CLIPBOARD_DATA,
) -> UINT,
>;
pub type pcCliprdrServerUnlockClipboardData = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
unlockClipboardData: *const CLIPRDR_UNLOCK_CLIPBOARD_DATA,
) -> UINT,
>;
pub type pcCliprdrClientFormatDataRequest = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
formatDataRequest: *const CLIPRDR_FORMAT_DATA_REQUEST,
) -> UINT,
>;
pub type pcCliprdrServerFormatDataRequest = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
formatDataRequest: *const CLIPRDR_FORMAT_DATA_REQUEST,
) -> UINT,
>;
pub type pcCliprdrClientFormatDataResponse = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
formatDataResponse: *const CLIPRDR_FORMAT_DATA_RESPONSE,
) -> UINT,
>;
pub type pcCliprdrServerFormatDataResponse = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
formatDataResponse: *const CLIPRDR_FORMAT_DATA_RESPONSE,
) -> UINT,
>;
pub type pcCliprdrClientFileContentsRequest = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
fileContentsRequest: *const CLIPRDR_FILE_CONTENTS_REQUEST,
) -> UINT,
>;
pub type pcCliprdrServerFileContentsRequest = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
fileContentsRequest: *const CLIPRDR_FILE_CONTENTS_REQUEST,
) -> UINT,
>;
pub type pcCliprdrClientFileContentsResponse = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
fileContentsResponse: *const CLIPRDR_FILE_CONTENTS_RESPONSE,
) -> UINT,
>;
pub type pcCliprdrServerFileContentsResponse = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
fileContentsResponse: *const CLIPRDR_FILE_CONTENTS_RESPONSE,
) -> UINT,
>;
pub type pcCheckEnabled = ::std::option::Option<
unsafe extern "C" fn(connID: UINT32) -> BOOL,
>;
// TODO: hide more members of clipboard context
#[repr(C)]
#[derive(Debug, Clone)]
pub struct _cliprdr_client_context {
pub custom: *mut ::std::os::raw::c_void,
pub enableFiles: BOOL,
pub enableOthers: BOOL,
pub CheckEnabled: pcCheckEnabled,
pub ServerCapabilities: pcCliprdrServerCapabilities,
pub ClientCapabilities: pcCliprdrClientCapabilities,
pub MonitorReady: pcCliprdrMonitorReady,
pub TempDirectory: pcCliprdrTempDirectory,
pub ClientFormatList: pcCliprdrClientFormatList,
pub ServerFormatList: pcCliprdrServerFormatList,
pub ClientFormatListResponse: pcCliprdrClientFormatListResponse,
pub ServerFormatListResponse: pcCliprdrServerFormatListResponse,
pub ClientLockClipboardData: pcCliprdrClientLockClipboardData,
pub ServerLockClipboardData: pcCliprdrServerLockClipboardData,
pub ClientUnlockClipboardData: pcCliprdrClientUnlockClipboardData,
pub ServerUnlockClipboardData: pcCliprdrServerUnlockClipboardData,
pub ClientFormatDataRequest: pcCliprdrClientFormatDataRequest,
pub ServerFormatDataRequest: pcCliprdrServerFormatDataRequest,
pub ClientFormatDataResponse: pcCliprdrClientFormatDataResponse,
pub ServerFormatDataResponse: pcCliprdrServerFormatDataResponse,
pub ClientFileContentsRequest: pcCliprdrClientFileContentsRequest,
pub ServerFileContentsRequest: pcCliprdrServerFileContentsRequest,
pub ClientFileContentsResponse: pcCliprdrClientFileContentsResponse,
pub ServerFileContentsResponse: pcCliprdrServerFileContentsResponse,
pub lastRequestedFormatId: UINT32,
}
// #[link(name = "user32")]
// #[link(name = "ole32")]
extern "C" {
pub(crate) fn init_cliprdr(context: *mut CliprdrClientContext) -> BOOL;
pub(crate) fn uninit_cliprdr(context: *mut CliprdrClientContext) -> BOOL;
pub(crate) fn empty_cliprdr(
context: *mut CliprdrClientContext,
connID: UINT32,
) -> BOOL;
}
#[derive(Error, Debug)]
pub enum CliprdrError {
#[error("invalid cliprdr name")]
CliprdrName,
#[error("failed to init cliprdr")]
CliprdrInit,
#[error("unknown cliprdr error")]
Unknown,
}
impl CliprdrClientContext {
pub fn create(
enable_files: bool,
enable_others: bool,
check_enabled: pcCheckEnabled,
client_format_list: pcCliprdrClientFormatList,
client_format_list_response: pcCliprdrClientFormatListResponse,
client_format_data_request: pcCliprdrClientFormatDataRequest,
client_format_data_response: pcCliprdrClientFormatDataResponse,
client_file_contents_request: pcCliprdrClientFileContentsRequest,
client_file_contents_response: pcCliprdrClientFileContentsResponse,
) -> Result<Box<Self>, CliprdrError> {
let context = CliprdrClientContext {
custom: 0 as *mut _,
enableFiles: if enable_files { TRUE } else { FALSE },
enableOthers: if enable_others { TRUE } else { FALSE },
CheckEnabled: check_enabled,
ServerCapabilities: None,
ClientCapabilities: None,
MonitorReady: None,
TempDirectory: None,
ClientFormatList: client_format_list,
ServerFormatList: None,
ClientFormatListResponse: client_format_list_response,
ServerFormatListResponse: None,
ClientLockClipboardData: None,
ServerLockClipboardData: None,
ClientUnlockClipboardData: None,
ServerUnlockClipboardData: None,
ClientFormatDataRequest: client_format_data_request,
ServerFormatDataRequest: None,
ClientFormatDataResponse: client_format_data_response,
ServerFormatDataResponse: None,
ClientFileContentsRequest: client_file_contents_request,
ServerFileContentsRequest: None,
ClientFileContentsResponse: client_file_contents_response,
ServerFileContentsResponse: None,
lastRequestedFormatId: 0,
};
let mut context = Box::new(context);
unsafe {
if FALSE == init_cliprdr(&mut (*context)) {
println!("Failed to init cliprdr");
Err(CliprdrError::CliprdrInit)
} else {
Ok(context)
}
}
}
}
impl Drop for CliprdrClientContext {
fn drop(&mut self) {
unsafe {
if FALSE == uninit_cliprdr(&mut *self) {
println!("Failed to uninit cliprdr");
} else {
println!("Succeeded to uninit cliprdr");
}
}
}
}

605
libs/clipboard/src/lib.rs Normal file
View File

@@ -0,0 +1,605 @@
use cliprdr::*;
use hbb_common::{
log,
tokio::sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
Mutex as TokioMutex,
},
ResultType,
};
use serde_derive::{Deserialize, Serialize};
use std::{
boxed::Box,
collections::HashMap,
ffi::{CStr, CString},
sync::Mutex,
};
pub mod cliprdr;
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "t", content = "c")]
pub enum ClipbaordFile {
ServerFormatList {
conn_id: i32,
format_list: Vec<(i32, String)>,
},
ServerFormatListResponse {
conn_id: i32,
msg_flags: i32,
},
ServerFormatDataRequest {
conn_id: i32,
requested_format_id: i32,
},
ServerFormatDataResponse {
conn_id: i32,
msg_flags: i32,
format_data: Vec<u8>,
},
FileContentsRequest {
conn_id: i32,
stream_id: i32,
list_index: i32,
dw_flags: i32,
n_position_low: i32,
n_position_high: i32,
cb_requested: i32,
have_clip_data_id: bool,
clip_data_id: i32,
},
FileContentsResponse {
conn_id: i32,
msg_flags: i32,
stream_id: i32,
requested_data: Vec<u8>,
},
}
#[derive(Default)]
struct ConnEnabled {
conn_enabled: HashMap<i32, bool>,
}
lazy_static::lazy_static! {
static ref MSG_CHANNEL_CLIENT: (UnboundedSender<(i32, ClipbaordFile)>, TokioMutex<UnboundedReceiver<(i32, ClipbaordFile)>>) = {
let (tx, rx) = unbounded_channel();
(tx, TokioMutex::new(rx))
};
static ref CLIP_CONN_ENABLED: Mutex<ConnEnabled> = Mutex::new(ConnEnabled::default());
}
#[inline(always)]
pub fn get_rx_clip_client<'a>() -> &'a TokioMutex<UnboundedReceiver<(i32, ClipbaordFile)>> {
&MSG_CHANNEL_CLIENT.1
}
pub fn set_conn_enabled(conn_id: i32, enabled: bool) {
let mut lock = CLIP_CONN_ENABLED.lock().unwrap();
if conn_id != 0 {
let _ = lock.conn_enabled.insert(conn_id, enabled);
}
}
pub fn empty_clipboard(context: &mut Box<CliprdrClientContext>, conn_id: i32) -> bool {
unsafe { TRUE == cliprdr::empty_cliprdr(&mut (**context), conn_id as u32) }
}
pub fn server_clip_file(
context: &mut Box<CliprdrClientContext>,
s_conn_id: i32,
msg: ClipbaordFile,
) -> u32 {
match msg {
ClipbaordFile::ServerFormatList {
mut conn_id,
format_list,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("server_format_list called");
let ret = server_format_list(context, conn_id, format_list);
log::debug!("server_format_list called, return {}", ret);
ret
}
ClipbaordFile::ServerFormatListResponse {
mut conn_id,
msg_flags,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("format_list_response called");
let ret = server_format_list_response(context, conn_id, msg_flags);
log::debug!("server_format_list_response called, return {}", ret);
ret
}
ClipbaordFile::ServerFormatDataRequest {
mut conn_id,
requested_format_id,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("format_data_request called");
let ret = server_format_data_request(context, conn_id, requested_format_id);
log::debug!("server_format_data_request called, return {}", ret);
ret
}
ClipbaordFile::ServerFormatDataResponse {
mut conn_id,
msg_flags,
format_data,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("format_data_response called");
let ret = server_format_data_response(context, conn_id, msg_flags, format_data);
log::debug!("server_format_data_response called, return {}", ret);
ret
}
ClipbaordFile::FileContentsRequest {
mut conn_id,
stream_id,
list_index,
dw_flags,
n_position_low,
n_position_high,
cb_requested,
have_clip_data_id,
clip_data_id,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("file_contents_request called");
let ret = server_file_contents_request(
context,
conn_id,
stream_id,
list_index,
dw_flags,
n_position_low,
n_position_high,
cb_requested,
have_clip_data_id,
clip_data_id,
);
log::debug!("server_file_contents_request called, return {}", ret);
ret
}
ClipbaordFile::FileContentsResponse {
mut conn_id,
msg_flags,
stream_id,
requested_data,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("file_contents_response called");
let ret = server_file_contents_response(
context,
conn_id,
msg_flags,
stream_id,
requested_data,
);
log::debug!("server_file_contents_response called, return {}", ret);
ret
}
}
}
pub fn server_format_list(
context: &mut Box<CliprdrClientContext>,
conn_id: i32,
format_list: Vec<(i32, String)>,
) -> u32 {
unsafe {
let num_formats = format_list.len() as UINT32;
let mut formats = format_list
.into_iter()
.map(|format| {
if format.1.is_empty() {
CLIPRDR_FORMAT {
formatId: format.0 as UINT32,
formatName: 0 as *mut _,
}
} else {
let n = match CString::new(format.1) {
Ok(n) => n,
Err(_) => CString::new("").unwrap(),
};
CLIPRDR_FORMAT {
formatId: format.0 as UINT32,
formatName: n.into_raw(),
}
}
})
.collect::<Vec<CLIPRDR_FORMAT>>();
let format_list = CLIPRDR_FORMAT_LIST {
connID: conn_id as UINT32,
msgType: 0 as UINT16,
msgFlags: 0 as UINT16,
dataLen: 0 as UINT32,
numFormats: num_formats,
formats: formats.as_mut_ptr(),
};
let ret = ((**context).ServerFormatList.unwrap())(&mut (**context), &format_list);
for f in formats {
if !f.formatName.is_null() {
// retake pointer to free memory
let _ = CString::from_raw(f.formatName);
}
}
ret as u32
}
}
pub fn server_format_list_response(
context: &mut Box<CliprdrClientContext>,
conn_id: i32,
msg_flags: i32,
) -> u32 {
unsafe {
let format_list_response = CLIPRDR_FORMAT_LIST_RESPONSE {
connID: conn_id as UINT32,
msgType: 0 as UINT16,
msgFlags: msg_flags as UINT16,
dataLen: 0 as UINT32,
};
let ret =
(**context).ServerFormatListResponse.unwrap()(&mut (**context), &format_list_response);
ret as u32
}
}
pub fn server_format_data_request(
context: &mut Box<CliprdrClientContext>,
conn_id: i32,
requested_format_id: i32,
) -> u32 {
unsafe {
let format_data_request = CLIPRDR_FORMAT_DATA_REQUEST {
connID: conn_id as UINT32,
msgType: 0 as UINT16,
msgFlags: 0 as UINT16,
dataLen: 0 as UINT32,
requestedFormatId: requested_format_id as UINT32,
};
let ret =
((**context).ServerFormatDataRequest.unwrap())(&mut (**context), &format_data_request);
ret as u32
}
}
pub fn server_format_data_response(
context: &mut Box<CliprdrClientContext>,
conn_id: i32,
msg_flags: i32,
mut format_data: Vec<u8>,
) -> u32 {
unsafe {
let format_data_response = CLIPRDR_FORMAT_DATA_RESPONSE {
connID: conn_id as UINT32,
msgType: 0 as UINT16,
msgFlags: msg_flags as UINT16,
dataLen: format_data.len() as UINT32,
requestedFormatData: format_data.as_mut_ptr(),
};
let ret = ((**context).ServerFormatDataResponse.unwrap())(
&mut (**context),
&format_data_response,
);
ret as u32
}
}
pub fn server_file_contents_request(
context: &mut Box<CliprdrClientContext>,
conn_id: i32,
stream_id: i32,
list_index: i32,
dw_flags: i32,
n_position_low: i32,
n_position_high: i32,
cb_requested: i32,
have_clip_data_id: bool,
clip_data_id: i32,
) -> u32 {
unsafe {
let file_contents_request = CLIPRDR_FILE_CONTENTS_REQUEST {
connID: conn_id as UINT32,
msgType: 0 as UINT16,
msgFlags: 0 as UINT16,
dataLen: 0 as UINT32,
streamId: stream_id as UINT32,
listIndex: list_index as UINT32,
dwFlags: dw_flags as UINT32,
nPositionLow: n_position_low as UINT32,
nPositionHigh: n_position_high as UINT32,
cbRequested: cb_requested as UINT32,
haveClipDataId: if have_clip_data_id { TRUE } else { FALSE },
clipDataId: clip_data_id as UINT32,
};
let ret = ((**context).ServerFileContentsRequest.unwrap())(
&mut (**context),
&file_contents_request,
);
ret as u32
}
}
pub fn server_file_contents_response(
context: &mut Box<CliprdrClientContext>,
conn_id: i32,
msg_flags: i32,
stream_id: i32,
mut requested_data: Vec<u8>,
) -> u32 {
unsafe {
let file_contents_response = CLIPRDR_FILE_CONTENTS_RESPONSE {
connID: conn_id as UINT32,
msgType: 0 as UINT16,
msgFlags: msg_flags as UINT16,
dataLen: 4 + requested_data.len() as UINT32,
streamId: stream_id as UINT32,
cbRequested: requested_data.len() as UINT32,
requestedData: requested_data.as_mut_ptr(),
};
let ret = ((**context).ServerFileContentsResponse.unwrap())(
&mut (**context),
&file_contents_response,
);
ret as u32
}
}
pub fn create_cliprdr_context(
enable_files: bool,
enable_others: bool,
) -> ResultType<Box<CliprdrClientContext>> {
Ok(CliprdrClientContext::create(
enable_files,
enable_others,
Some(check_enabled),
Some(client_format_list),
Some(client_format_list_response),
Some(client_format_data_request),
Some(client_format_data_response),
Some(client_file_contents_request),
Some(client_file_contents_response),
)?)
}
extern "C" fn check_enabled(conn_id: UINT32) -> BOOL {
let lock = CLIP_CONN_ENABLED.lock().unwrap();
let mut connd_enabled = false;
if conn_id != 0 {
if let Some(true) = lock.conn_enabled.get(&(conn_id as i32)) {
connd_enabled = true;
}
} else {
connd_enabled = true;
}
return if connd_enabled { TRUE } else { FALSE };
}
extern "C" fn client_format_list(
_context: *mut CliprdrClientContext,
clip_format_list: *const CLIPRDR_FORMAT_LIST,
) -> UINT {
log::debug!("client_format_list called");
let conn_id;
let mut format_list: Vec<(i32, String)> = Vec::new();
unsafe {
let mut i = 0u32;
while i < (*clip_format_list).numFormats {
let format_data = &(*(*clip_format_list).formats.offset(i as isize));
if format_data.formatName.is_null() {
format_list.push((format_data.formatId as i32, "".to_owned()));
} else {
let format_name = CStr::from_ptr(format_data.formatName).to_str();
let format_name = match format_name {
Ok(n) => n.to_owned(),
Err(_) => {
log::warn!("failed to get format name");
"".to_owned()
}
};
format_list.push((format_data.formatId as i32, format_name));
}
// log::debug!("format list item {}: format id: {}, format name: {}", i, format_data.formatId, &format_name);
i += 1;
}
conn_id = (*clip_format_list).connID as i32;
}
let data = ClipbaordFile::ServerFormatList {
conn_id,
format_list,
};
// no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
0
}
extern "C" fn client_format_list_response(
_context: *mut CliprdrClientContext,
format_list_response: *const CLIPRDR_FORMAT_LIST_RESPONSE,
) -> UINT {
log::debug!("client_format_list_response called");
let conn_id;
let msg_flags;
unsafe {
conn_id = (*format_list_response).connID as i32;
msg_flags = (*format_list_response).msgFlags as i32;
}
let data = ClipbaordFile::ServerFormatListResponse { conn_id, msg_flags };
// no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
0
}
extern "C" fn client_format_data_request(
_context: *mut CliprdrClientContext,
format_data_request: *const CLIPRDR_FORMAT_DATA_REQUEST,
) -> UINT {
log::debug!("client_format_data_request called");
let conn_id;
let requested_format_id;
unsafe {
conn_id = (*format_data_request).connID as i32;
requested_format_id = (*format_data_request).requestedFormatId as i32;
}
let data = ClipbaordFile::ServerFormatDataRequest {
conn_id,
requested_format_id,
};
// no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
0
}
extern "C" fn client_format_data_response(
_context: *mut CliprdrClientContext,
format_data_response: *const CLIPRDR_FORMAT_DATA_RESPONSE,
) -> UINT {
log::debug!("cconn_idlient_format_data_response called");
let conn_id;
let msg_flags;
let format_data;
unsafe {
conn_id = (*format_data_response).connID as i32;
msg_flags = (*format_data_response).msgFlags as i32;
if (*format_data_response).requestedFormatData.is_null() {
format_data = Vec::new();
} else {
format_data = std::slice::from_raw_parts(
(*format_data_response).requestedFormatData,
(*format_data_response).dataLen as usize,
)
.to_vec();
}
}
let data = ClipbaordFile::ServerFormatDataResponse {
conn_id,
msg_flags,
format_data,
};
// no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
0
}
extern "C" fn client_file_contents_request(
_context: *mut CliprdrClientContext,
file_contents_request: *const CLIPRDR_FILE_CONTENTS_REQUEST,
) -> UINT {
log::debug!("client_file_contents_request called");
// TODO: support huge file?
// if (!cliprdr->hasHugeFileSupport)
// {
// if (((UINT64)fileContentsRequest->cbRequested + fileContentsRequest->nPositionLow) >
// UINT32_MAX)
// return ERROR_INVALID_PARAMETER;
// if (fileContentsRequest->nPositionHigh != 0)
// return ERROR_INVALID_PARAMETER;
// }
let conn_id;
let stream_id;
let list_index;
let dw_flags;
let n_position_low;
let n_position_high;
let cb_requested;
let have_clip_data_id;
let clip_data_id;
unsafe {
conn_id = (*file_contents_request).connID as i32;
stream_id = (*file_contents_request).streamId as i32;
list_index = (*file_contents_request).listIndex as i32;
dw_flags = (*file_contents_request).dwFlags as i32;
n_position_low = (*file_contents_request).nPositionLow as i32;
n_position_high = (*file_contents_request).nPositionHigh as i32;
cb_requested = (*file_contents_request).cbRequested as i32;
have_clip_data_id = (*file_contents_request).haveClipDataId == TRUE;
clip_data_id = (*file_contents_request).clipDataId as i32;
}
let data = ClipbaordFile::FileContentsRequest {
conn_id,
stream_id,
list_index,
dw_flags,
n_position_low,
n_position_high,
cb_requested,
have_clip_data_id,
clip_data_id,
};
// no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
0
}
extern "C" fn client_file_contents_response(
_context: *mut CliprdrClientContext,
file_contents_response: *const CLIPRDR_FILE_CONTENTS_RESPONSE,
) -> UINT {
log::debug!("client_file_contents_response called");
let conn_id;
let msg_flags;
let stream_id;
let requested_data;
unsafe {
conn_id = (*file_contents_response).connID as i32;
msg_flags = (*file_contents_response).msgFlags as i32;
stream_id = (*file_contents_response).streamId as i32;
if (*file_contents_response).requestedData.is_null() {
requested_data = Vec::new();
} else {
requested_data = std::slice::from_raw_parts(
(*file_contents_response).requestedData,
(*file_contents_response).cbRequested as usize,
)
.to_vec();
}
}
let data = ClipbaordFile::FileContentsResponse {
conn_id,
msg_flags,
stream_id,
requested_data,
};
// no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
0
}
#[cfg(test)]
mod tests {
// #[test]
// fn test_cliprdr_run() {
// super::cliprdr_run();
// }
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ fn main() {
thread::sleep(Duration::from_secs(2));
let mut enigo = Enigo::new();
enigo.key_down(Key::Layout('a'));
enigo.key_down(Key::Layout('a')).ok();
thread::sleep(Duration::from_secs(1));
enigo.key_up(Key::Layout('a'));
}

View File

@@ -10,7 +10,7 @@ fn main() {
enigo.key_sequence("Hello World! here is a lot of text ❤️");
// select all
enigo.key_down(Key::Control);
enigo.key_down(Key::Control).ok();
enigo.key_click(Key::Layout('a'));
enigo.key_up(Key::Control);
}

View File

@@ -11,7 +11,7 @@ fn main() {
enigo.mouse_move_to(500, 200);
thread::sleep(wait_time);
enigo.mouse_down(MouseButton::Left);
enigo.mouse_down(MouseButton::Left).ok();
thread::sleep(wait_time);
enigo.mouse_move_relative(100, 100);

View File

@@ -16,7 +16,7 @@ fn main() {
println!("{:?}", time);
// select all
enigo.key_down(Key::Control);
enigo.key_down(Key::Control).ok();
enigo.key_click(Key::Layout('a'));
enigo.key_up(Key::Control);
}

View File

@@ -299,7 +299,7 @@ pub enum Key {
/// meta key (also known as "windows", "super", and "command")
Meta,
/// option key on macOS (alt key on Linux and Windows)
Option,
Option, // deprecated, use Alt instead
/// page down key
PageDown,
/// page up key
@@ -347,8 +347,6 @@ pub enum Key {
///
Clear,
///
Menu,
///
Pause,
///
Kana,
@@ -409,6 +407,12 @@ pub enum Key {
///
NumpadEnter,
///
RightShift,
///
RightControl,
///
RightAlt,
///
/// Function, /// mac
/// keyboard layout dependent key
Layout(char),
@@ -485,7 +489,7 @@ impl Enigo {
/// ```
pub fn new() -> Self {
#[cfg(any(target_os = "android", target_os = "ios"))]
return Enigo{};
return Enigo {};
#[cfg(not(any(target_os = "android", target_os = "ios")))]
Self::default()
}

View File

@@ -3,7 +3,7 @@ use libc;
use crate::{Key, KeyboardControllable, MouseButton, MouseControllable};
use self::libc::{c_char, c_int, c_void, useconds_t};
use std::{borrow::Cow, ffi::CString, ptr};
use std::{borrow::Cow, ffi::CString, io::prelude::*, ptr, sync::mpsc};
const CURRENT_WINDOW: c_int = 0;
const DEFAULT_DELAY: u64 = 12000;
@@ -60,10 +60,16 @@ fn mousebutton(button: MouseButton) -> c_int {
}
}
enum PyMsg {
Char(char),
Str(&'static str),
}
/// The main struct for handling the event emitting
pub struct Enigo {
xdo: Xdo,
delay: u64,
tx: mpsc::Sender<(PyMsg, bool)>,
}
// This is safe, we have a unique pointer.
// TODO: use Unique<c_char> once stable.
@@ -72,9 +78,12 @@ unsafe impl Send for Enigo {}
impl Default for Enigo {
/// Create a new Enigo instance
fn default() -> Self {
let (tx, rx) = mpsc::channel();
start_pynput_service(rx);
Self {
xdo: unsafe { xdo_new(ptr::null()) },
delay: DEFAULT_DELAY,
tx,
}
}
}
@@ -90,6 +99,99 @@ impl Enigo {
pub fn set_delay(&mut self, delay: u64) {
self.delay = delay;
}
///
pub fn reset(&mut self) {
self.tx.send((PyMsg::Char('\0'), true)).ok();
}
#[inline]
fn send_pynput(&mut self, key: &Key, is_press: bool) -> bool {
if unsafe { PYNPUT_EXIT || !PYNPUT_REDAY } {
return false;
}
if let Key::Layout(c) = key {
return self.tx.send((PyMsg::Char(*c), is_press)).is_ok();
}
if let Key::Raw(_) = key {
return false;
}
#[allow(deprecated)]
let s = match key {
Key::Alt => "Alt_L",
Key::Backspace => "BackSpace",
Key::CapsLock => "Caps_Lock",
Key::Control => "Control_L",
Key::Delete => "Delete",
Key::DownArrow => "Down",
Key::End => "End",
Key::Escape => "Escape",
Key::F1 => "F1",
Key::F10 => "F10",
Key::F11 => "F11",
Key::F12 => "F12",
Key::F2 => "F2",
Key::F3 => "F3",
Key::F4 => "F4",
Key::F5 => "F5",
Key::F6 => "F6",
Key::F7 => "F7",
Key::F8 => "F8",
Key::F9 => "F9",
Key::Home => "Home",
Key::LeftArrow => "Left",
Key::Option => "Option",
Key::PageDown => "Page_Down",
Key::PageUp => "Page_Up",
Key::Return => "Return",
Key::RightArrow => "Right",
Key::Shift => "Shift_L",
Key::Space => "space",
Key::Tab => "Tab",
Key::UpArrow => "Up",
Key::Numpad0 => "0",
Key::Numpad1 => "1",
Key::Numpad2 => "2",
Key::Numpad3 => "3",
Key::Numpad4 => "4",
Key::Numpad5 => "5",
Key::Numpad6 => "6",
Key::Numpad7 => "7",
Key::Numpad8 => "8",
Key::Numpad9 => "9",
Key::Decimal => "KP_Decimal",
Key::Cancel => "Cancel",
Key::Clear => "Clear",
Key::Pause => "Pause",
Key::Kana => "Kana",
Key::Hangul => "Hangul",
Key::Hanja => "Hanja",
Key::Kanji => "Kanji",
Key::Select => "Select",
Key::Print => "Print",
Key::Execute => "Execute",
Key::Snapshot => "3270_PrintScreen",
Key::Insert => "Insert",
Key::Help => "Help",
Key::Separator => "KP_Separator",
Key::Scroll => "Scroll_Lock",
Key::NumLock => "Num_Lock",
Key::RWin => "Super_R",
Key::Apps => "Menu",
Key::Multiply => "KP_Multiply",
Key::Add => "KP_Add",
Key::Subtract => "KP_Subtract",
Key::Divide => "KP_Divide",
Key::Equals => "KP_Equal",
Key::NumpadEnter => "KP_Enter",
Key::RightShift => "Shift_R",
Key::RightControl => "Control_R",
Key::RightAlt => "Mode_switch",
Key::Command | Key::Super | Key::Windows | Key::Meta => "Super_L",
_ => {
return true;
}
};
return self.tx.send((PyMsg::Str(s), is_press)).is_ok();
}
}
impl Drop for Enigo {
fn drop(&mut self) {
@@ -238,7 +340,6 @@ fn keysequence<'a>(key: Key) -> Cow<'a, str> {
Key::Decimal => "U2E", //"KP_Decimal",
Key::Cancel => "Cancel",
Key::Clear => "Clear",
Key::Menu => "Menu",
Key::Pause => "Pause",
Key::Kana => "Kana",
Key::Hangul => "Hangul",
@@ -260,14 +361,17 @@ fn keysequence<'a>(key: Key) -> Cow<'a, str> {
Key::Mute => "",
Key::Scroll => "Scroll_Lock",
Key::NumLock => "Num_Lock",
Key::RWin => "",
Key::Apps => "",
Key::RWin => "Super_R",
Key::Apps => "Menu",
Key::Multiply => "KP_Multiply",
Key::Add => "KP_Add",
Key::Subtract => "KP_Subtract",
Key::Divide => "KP_Divide",
Key::Equals => "KP_Equal",
Key::NumpadEnter => "KP_Enter",
Key::RightShift => "Shift_R",
Key::RightControl => "Control_R",
Key::RightAlt => "Alt_R",
Key::Command | Key::Super | Key::Windows | Key::Meta => "Super",
@@ -279,6 +383,17 @@ impl KeyboardControllable for Enigo {
if self.xdo.is_null() {
return false;
}
/*
// modifier keys mask
pub const ShiftMask: c_uint = 0x01;
pub const LockMask: c_uint = 0x02;
pub const ControlMask: c_uint = 0x04;
pub const Mod1Mask: c_uint = 0x08;
pub const Mod2Mask: c_uint = 0x10;
pub const Mod3Mask: c_uint = 0x20;
pub const Mod4Mask: c_uint = 0x40;
pub const Mod5Mask: c_uint = 0x80;
*/
let mod_shift = 1 << 0;
let mod_lock = 1 << 1;
let mod_control = 1 << 2;
@@ -286,7 +401,6 @@ impl KeyboardControllable for Enigo {
let mod_numlock = 1 << 4;
let mod_meta = 1 << 6;
let mask = unsafe { xdo_get_input_state(self.xdo) };
// println!("{:b}", mask);
match key {
Key::Shift => mask & mod_shift != 0,
Key::CapsLock => mask & mod_lock != 0,
@@ -317,6 +431,9 @@ impl KeyboardControllable for Enigo {
if self.xdo.is_null() {
return Ok(());
}
if self.send_pynput(&key, true) {
return Ok(());
}
let string = CString::new(&*keysequence(key))?;
unsafe {
xdo_send_keysequence_window_down(
@@ -332,6 +449,9 @@ impl KeyboardControllable for Enigo {
if self.xdo.is_null() {
return;
}
if self.send_pynput(&key, false) {
return;
}
if let Ok(string) = CString::new(&*keysequence(key)) {
unsafe {
xdo_send_keysequence_window_up(
@@ -359,3 +479,119 @@ impl KeyboardControllable for Enigo {
}
}
}
static mut PYNPUT_EXIT: bool = false;
static mut PYNPUT_REDAY: bool = false;
static IPC_FILE: &'static str = "/tmp/RustDesk/pynput_service";
fn start_pynput_service(rx: mpsc::Receiver<(PyMsg, bool)>) {
let mut py = "./pynput_service.py".to_owned();
if !std::path::Path::new(&py).exists() {
py = "/usr/share/rustdesk/files/pynput_service.py".to_owned();
if !std::path::Path::new(&py).exists() {
log::error!("{} not exits", py);
}
}
log::info!("pynput service: {}", py);
std::thread::spawn(move || {
let username = std::env::var("PYNPUT_USERNAME").unwrap_or("".to_owned());
let userid = std::env::var("PYNPUT_USERID").unwrap_or("".to_owned());
let status = if username.is_empty() {
std::process::Command::new("python3")
.arg(&py)
.arg(IPC_FILE)
.status()
.map(|x| x.success())
} else {
let mut status = Ok(true);
for i in 0..100 {
if i % 10 == 0 {
log::info!("#{} try to start pynput server", i);
}
status = std::process::Command::new("sudo")
.args(vec![
&format!("XDG_RUNTIME_DIR=/run/user/{}", userid) as &str,
"-u",
&username,
"python3",
&py,
IPC_FILE,
])
.status()
.map(|x| x.success());
match status {
Ok(true) => break,
_ => {}
}
std::thread::sleep(std::time::Duration::from_millis(100));
}
status
};
log::info!(
"pynput server exit with username/id {}/{}: {:?}",
username,
userid,
status
);
unsafe {
PYNPUT_EXIT = true;
}
});
std::thread::spawn(move || {
for i in 0..300 {
std::thread::sleep(std::time::Duration::from_millis(100));
let mut conn = match std::os::unix::net::UnixStream::connect(IPC_FILE) {
Ok(conn) => conn,
Err(err) => {
if i % 15 == 0 {
log::warn!("Failed to connect to {}: {}", IPC_FILE, err);
}
continue;
}
};
if let Err(err) = conn.set_nonblocking(true) {
log::error!("Failed to set ipc nonblocking: {}", err);
return;
}
log::info!("Conntected to pynput server");
let d = std::time::Duration::from_millis(30);
unsafe {
PYNPUT_REDAY = true;
}
let mut buf = [0u8; 1024];
loop {
if unsafe { PYNPUT_EXIT } {
break;
}
match rx.recv_timeout(d) {
Ok((msg, is_press)) => {
let msg = match msg {
PyMsg::Char(chr) => {
format!("{}{}", if is_press { 'p' } else { 'r' }, chr)
}
PyMsg::Str(s) => format!("{}{}", if is_press { 'p' } else { 'r' }, s),
};
let n = msg.len();
buf[0] = n as _;
buf[1..(n + 1)].copy_from_slice(msg.as_bytes());
if let Err(err) = conn.write_all(&buf[..n + 1]) {
log::error!("Failed to write to ipc: {}", err);
break;
}
}
Err(err) => match err {
mpsc::RecvTimeoutError::Disconnected => {
log::error!("pynput sender disconnecte");
break;
}
_ => {}
},
}
}
unsafe {
PYNPUT_REDAY = false;
}
break;
}
});
}

View File

@@ -70,3 +70,51 @@ pub const kVK_ANSI_KeypadDivide: u16 = 0x4B;
pub const kVK_ANSI_KeypadEnter: u16 = 0x4C;
pub const kVK_ANSI_KeypadMinus: u16 = 0x4E;
pub const kVK_ANSI_KeypadEquals: u16 = 0x51;
pub const kVK_RIGHT_COMMAND: u16 = 0x36;
pub const kVK_ANSI_A : u16 = 0x00;
pub const kVK_ANSI_S : u16 = 0x01;
pub const kVK_ANSI_D : u16 = 0x02;
pub const kVK_ANSI_F : u16 = 0x03;
pub const kVK_ANSI_H : u16 = 0x04;
pub const kVK_ANSI_G : u16 = 0x05;
pub const kVK_ANSI_Z : u16 = 0x06;
pub const kVK_ANSI_X : u16 = 0x07;
pub const kVK_ANSI_C : u16 = 0x08;
pub const kVK_ANSI_V : u16 = 0x09;
pub const kVK_ANSI_B : u16 = 0x0B;
pub const kVK_ANSI_Q : u16 = 0x0C;
pub const kVK_ANSI_W : u16 = 0x0D;
pub const kVK_ANSI_E : u16 = 0x0E;
pub const kVK_ANSI_R : u16 = 0x0F;
pub const kVK_ANSI_Y : u16 = 0x10;
pub const kVK_ANSI_T : u16 = 0x11;
pub const kVK_ANSI_1 : u16 = 0x12;
pub const kVK_ANSI_2 : u16 = 0x13;
pub const kVK_ANSI_3 : u16 = 0x14;
pub const kVK_ANSI_4 : u16 = 0x15;
pub const kVK_ANSI_6 : u16 = 0x16;
pub const kVK_ANSI_5 : u16 = 0x17;
pub const kVK_ANSI_Equal : u16 = 0x18;
pub const kVK_ANSI_9 : u16 = 0x19;
pub const kVK_ANSI_7 : u16 = 0x1A;
pub const kVK_ANSI_Minus : u16 = 0x1B;
pub const kVK_ANSI_8 : u16 = 0x1C;
pub const kVK_ANSI_0 : u16 = 0x1D;
pub const kVK_ANSI_RightBracket : u16 = 0x1E;
pub const kVK_ANSI_O : u16 = 0x1F;
pub const kVK_ANSI_U : u16 = 0x20;
pub const kVK_ANSI_LeftBracket : u16 = 0x21;
pub const kVK_ANSI_I : u16 = 0x22;
pub const kVK_ANSI_P : u16 = 0x23;
pub const kVK_ANSI_L : u16 = 0x25;
pub const kVK_ANSI_J : u16 = 0x26;
pub const kVK_ANSI_Quote : u16 = 0x27;
pub const kVK_ANSI_K : u16 = 0x28;
pub const kVK_ANSI_Semicolon : u16 = 0x29;
pub const kVK_ANSI_Backslash : u16 = 0x2A;
pub const kVK_ANSI_Comma : u16 = 0x2B;
pub const kVK_ANSI_Slash : u16 = 0x2C;
pub const kVK_ANSI_N : u16 = 0x2D;
pub const kVK_ANSI_M : u16 = 0x2E;
pub const kVK_ANSI_Period : u16 = 0x2F;
pub const kVK_ANSI_Grave : u16 = 0x32;

View File

@@ -5,24 +5,73 @@ use core_graphics;
use self::core_graphics::display::*;
use self::core_graphics::event::*;
use self::core_graphics::event_source::*;
use std::collections::HashMap as Map;
use std::ffi::c_void;
use std::ffi::CStr;
use std::os::raw::*;
use std::ptr::null_mut;
use crate::macos::keycodes::*;
use crate::{Key, KeyboardControllable, MouseButton, MouseControllable};
use objc::runtime::Class;
use std::ffi::CStr;
use std::os::raw::*;
// required for pressedMouseButtons on NSEvent
#[link(name = "AppKit", kind = "framework")]
extern "C" {}
struct MyCGEvent;
type TISInputSourceRef = *mut c_void;
type CFDataRef = *const c_void;
type OptionBits = u32;
type OSStatus = i32;
type UniChar = u16;
type UniCharCount = usize;
type Boolean = c_uchar;
type CFStringEncoding = u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct __CFString([u8; 0]);
type CFStringRef = *const __CFString;
#[allow(non_upper_case_globals)]
const kCFStringEncodingUTF8: u32 = 134_217_984;
#[allow(non_upper_case_globals)]
const kUCKeyActionDisplay: u16 = 3;
#[allow(non_upper_case_globals)]
const kUCKeyTranslateDeadKeysBit: OptionBits = 1 << 31;
const BUF_LEN: usize = 4;
#[allow(improper_ctypes)]
#[allow(non_snake_case)]
#[link(name = "ApplicationServices", kind = "framework")]
extern "C" {
fn CFDataGetBytePtr(theData: CFDataRef) -> *const u8;
fn TISCopyCurrentKeyboardInputSource() -> TISInputSourceRef;
fn TISCopyCurrentKeyboardLayoutInputSource() -> TISInputSourceRef;
fn TISCopyCurrentASCIICapableKeyboardLayoutInputSource() -> TISInputSourceRef;
static kTISPropertyUnicodeKeyLayoutData: *mut c_void;
static kTISPropertyInputSourceID: *mut c_void;
fn UCKeyTranslate(
keyLayoutPtr: *const u8, //*const UCKeyboardLayout,
virtualKeyCode: u16,
keyAction: u16,
modifierKeyState: u32,
keyboardType: u32,
keyTranslateOptions: OptionBits,
deadKeyState: *mut u32,
maxStringLength: UniCharCount,
actualStringLength: *mut UniCharCount,
unicodeString: *mut [UniChar; BUF_LEN],
) -> OSStatus;
fn LMGetKbdType() -> u8;
fn CFStringGetCString(
theString: CFStringRef,
buffer: *mut c_char,
bufferSize: CFIndex,
encoding: CFStringEncoding,
) -> Boolean;
fn CGEventPost(tapLocation: CGEventTapLocation, event: *mut MyCGEvent);
// Actually return CFDataRef which is const here, but for coding convienence, return *mut c_void
fn TISGetInputSourceProperty(source: TISInputSourceRef, property: *const c_void)
-> *mut c_void;
// not present in servo/core-graphics
fn CGEventCreateScrollWheelEvent(
source: &CGEventSourceRef,
@@ -34,8 +83,6 @@ extern "C" {
fn CGEventSourceKeyState(stateID: i32, key: u16) -> bool;
}
pub type CFDataRef = *const c_void;
#[repr(C)]
#[derive(Clone, Copy)]
struct NSPoint {
@@ -43,160 +90,6 @@ struct NSPoint {
y: f64,
}
#[repr(C)]
pub struct __TISInputSource;
pub type TISInputSourceRef = *const __TISInputSource;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct __CFString([u8; 0]);
pub type CFStringRef = *const __CFString;
pub type Boolean = c_uchar;
pub type UInt8 = c_uchar;
pub type SInt32 = c_int;
pub type UInt16 = c_ushort;
pub type UInt32 = c_uint;
pub type UniChar = UInt16;
pub type UniCharCount = c_ulong;
pub type OptionBits = UInt32;
pub type OSStatus = SInt32;
pub type CFStringEncoding = UInt32;
#[allow(non_upper_case_globals)]
pub const kUCKeyActionDisplay: _bindgen_ty_702 = _bindgen_ty_702::kUCKeyActionDisplay;
#[allow(non_camel_case_types)]
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_702 {
// kUCKeyActionDown = 0,
// kUCKeyActionUp = 1,
// kUCKeyActionAutoKey = 2,
kUCKeyActionDisplay = 3,
}
#[allow(non_snake_case)]
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct UCKeyboardTypeHeader {
pub keyboardTypeFirst: UInt32,
pub keyboardTypeLast: UInt32,
pub keyModifiersToTableNumOffset: UInt32,
pub keyToCharTableIndexOffset: UInt32,
pub keyStateRecordsIndexOffset: UInt32,
pub keyStateTerminatorsOffset: UInt32,
pub keySequenceDataIndexOffset: UInt32,
}
#[allow(non_snake_case)]
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct UCKeyboardLayout {
pub keyLayoutHeaderFormat: UInt16,
pub keyLayoutDataVersion: UInt16,
pub keyLayoutFeatureInfoOffset: UInt32,
pub keyboardTypeCount: UInt32,
pub keyboardTypeList: [UCKeyboardTypeHeader; 1usize],
}
#[allow(non_upper_case_globals)]
pub const kUCKeyTranslateNoDeadKeysBit: _bindgen_ty_703 =
_bindgen_ty_703::kUCKeyTranslateNoDeadKeysBit;
#[allow(non_camel_case_types)]
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_703 {
kUCKeyTranslateNoDeadKeysBit = 0,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct __CFAllocator([u8; 0]);
pub type CFAllocatorRef = *const __CFAllocator;
// #[repr(u32)]
// #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
// pub enum _bindgen_ty_15 {
// kCFStringEncodingMacRoman = 0,
// kCFStringEncodingWindowsLatin1 = 1280,
// kCFStringEncodingISOLatin1 = 513,
// kCFStringEncodingNextStepLatin = 2817,
// kCFStringEncodingASCII = 1536,
// kCFStringEncodingUnicode = 256,
// kCFStringEncodingUTF8 = 134217984,
// kCFStringEncodingNonLossyASCII = 3071,
// kCFStringEncodingUTF16BE = 268435712,
// kCFStringEncodingUTF16LE = 335544576,
// kCFStringEncodingUTF32 = 201326848,
// kCFStringEncodingUTF32BE = 402653440,
// kCFStringEncodingUTF32LE = 469762304,
// }
#[allow(non_upper_case_globals)]
pub const kCFStringEncodingUTF8: u32 = 134_217_984;
#[allow(improper_ctypes)]
#[link(name = "Carbon", kind = "framework")]
extern "C" {
fn TISCopyCurrentKeyboardInputSource() -> TISInputSourceRef;
// extern void *
// TISGetInputSourceProperty(
// TISInputSourceRef inputSource,
// CFStringRef propertyKey)
#[allow(non_upper_case_globals)]
#[link_name = "kTISPropertyUnicodeKeyLayoutData"]
pub static kTISPropertyUnicodeKeyLayoutData: CFStringRef;
#[allow(non_snake_case)]
pub fn TISGetInputSourceProperty(
inputSource: TISInputSourceRef,
propertyKey: CFStringRef,
) -> *mut c_void;
#[allow(non_snake_case)]
pub fn CFDataGetBytePtr(theData: CFDataRef) -> *const UInt8;
#[allow(non_snake_case)]
pub fn UCKeyTranslate(
keyLayoutPtr: *const UInt8, //*const UCKeyboardLayout,
virtualKeyCode: UInt16,
keyAction: UInt16,
modifierKeyState: UInt32,
keyboardType: UInt32,
keyTranslateOptions: OptionBits,
deadKeyState: *mut UInt32,
maxStringLength: UniCharCount,
actualStringLength: *mut UniCharCount,
unicodeString: *mut UniChar,
) -> OSStatus;
pub fn LMGetKbdType() -> UInt8;
#[allow(non_snake_case)]
pub fn CFStringCreateWithCharacters(
alloc: CFAllocatorRef,
chars: *const UniChar,
numChars: CFIndex,
) -> CFStringRef;
#[allow(non_upper_case_globals)]
#[link_name = "kCFAllocatorDefault"]
pub static kCFAllocatorDefault: CFAllocatorRef;
#[allow(non_snake_case)]
pub fn CFStringGetCString(
theString: CFStringRef,
buffer: *mut c_char,
bufferSize: CFIndex,
encoding: CFStringEncoding,
) -> Boolean;
}
// not present in servo/core-graphics
#[allow(dead_code)]
#[derive(Debug)]
@@ -209,11 +102,11 @@ enum ScrollUnit {
/// The main struct for handling the event emitting
pub struct Enigo {
event_source: Option<CGEventSource>,
keycode_to_string_map: std::collections::HashMap<String, CGKeyCode>,
double_click_interval: u32,
last_click_time: Option<std::time::Instant>,
multiple_click: i64,
flags: CGEventFlags,
char_to_vkey_map: Map<String, Map<char, CGKeyCode>>,
}
impl Enigo {
@@ -261,11 +154,11 @@ impl Default for Enigo {
} else {
None
},
keycode_to_string_map: Default::default(),
double_click_interval,
multiple_click: 1,
last_click_time: None,
flags: CGEventFlags::CGEventFlagNull,
char_to_vkey_map: Default::default(),
}
}
}
@@ -583,98 +476,192 @@ impl Enigo {
Key::Subtract => kVK_ANSI_KeypadMinus,
Key::Equals => kVK_ANSI_KeypadEquals,
Key::NumLock => kVK_ANSI_KeypadClear,
Key::RWin => kVK_RIGHT_COMMAND,
Key::RightShift => kVK_RightShift,
Key::RightControl => kVK_RightControl,
Key::RightAlt => kVK_RightOption,
Key::Raw(raw_keycode) => raw_keycode,
Key::Layout(c) => self.get_layoutdependent_keycode(c.to_string()),
Key::Layout(c) => self.map_key_board(c),
Key::Super | Key::Command | Key::Windows | Key::Meta => kVK_Command,
_ => 0,
}
}
fn get_layoutdependent_keycode(&mut self, string: String) -> CGKeyCode {
if self.keycode_to_string_map.is_empty() {
self.init_map();
}
*self.keycode_to_string_map.get(&string).unwrap_or(&0)
}
fn init_map(&mut self) {
self.keycode_to_string_map.insert("".to_owned(), 0);
// loop through every keycode (0 - 127)
for keycode in 0..128 {
// no modifier
if let Some(key_string) = self.keycode_to_string(keycode, 0x100) {
self.keycode_to_string_map.insert(key_string, keycode);
}
// shift modifier
if let Some(key_string) = self.keycode_to_string(keycode, 0x20102) {
self.keycode_to_string_map.insert(key_string, keycode);
}
// alt modifier
// if let Some(string) = self.keycode_to_string(keycode, 0x80120) {
// println!("{:?}", string);
// }
// alt + shift modifier
// if let Some(string) = self.keycode_to_string(keycode, 0xa0122) {
// println!("{:?}", string);
// }
}
}
fn keycode_to_string(&self, keycode: u16, modifier: u32) -> Option<String> {
let cf_string = self.create_string_for_key(keycode, modifier);
#[inline]
fn map_key_board(&mut self, ch: char) -> CGKeyCode {
let mut code = 0;
unsafe {
if !cf_string.is_null() {
let mut buf: [i8; 255] = [0; 255];
let success = CFStringGetCString(
cf_string,
buf.as_mut_ptr(),
buf.len() as _,
kCFStringEncodingUTF8,
);
if success != 0 {
let name: &CStr = CStr::from_ptr(buf.as_ptr());
if let Ok(name) = name.to_str() {
return Some(name.to_owned());
let (keyboard, layout) = get_layout();
if !keyboard.is_null() && !layout.is_null() {
let name_ref = TISGetInputSourceProperty(keyboard, kTISPropertyInputSourceID);
if !name_ref.is_null() {
let name = get_string(name_ref as _);
if let Some(name) = name {
if let Some(m) = self.char_to_vkey_map.get(&name) {
code = *m.get(&ch).unwrap_or(&0);
} else {
let m = get_map(&name, layout);
code = *m.get(&ch).unwrap_or(&0);
self.char_to_vkey_map.insert(name.clone(), m);
}
}
}
}
if !keyboard.is_null() {
CFRelease(keyboard);
}
}
None
}
fn create_string_for_key(&self, keycode: u16, modifier: u32) -> CFStringRef {
let current_keyboard = unsafe { TISCopyCurrentKeyboardInputSource() };
let layout_data = unsafe {
TISGetInputSourceProperty(current_keyboard, kTISPropertyUnicodeKeyLayoutData)
};
let keyboard_layout = unsafe { CFDataGetBytePtr(layout_data) };
let mut keys_down: UInt32 = 0;
// let mut chars: *mut c_void;//[UniChar; 4];
let mut chars: u16 = 0;
let mut real_length: UniCharCount = 0;
unsafe {
UCKeyTranslate(
keyboard_layout,
keycode,
kUCKeyActionDisplay as u16,
modifier,
LMGetKbdType() as u32,
kUCKeyTranslateNoDeadKeysBit as u32,
&mut keys_down,
8, // sizeof(chars) / sizeof(chars[0]),
&mut real_length,
&mut chars,
);
if code > 0 {
return code;
}
match ch {
'a' => kVK_ANSI_A,
'b' => kVK_ANSI_B,
'c' => kVK_ANSI_C,
'd' => kVK_ANSI_D,
'e' => kVK_ANSI_E,
'f' => kVK_ANSI_F,
'g' => kVK_ANSI_G,
'h' => kVK_ANSI_H,
'i' => kVK_ANSI_I,
'j' => kVK_ANSI_J,
'k' => kVK_ANSI_K,
'l' => kVK_ANSI_L,
'm' => kVK_ANSI_M,
'n' => kVK_ANSI_N,
'o' => kVK_ANSI_O,
'p' => kVK_ANSI_P,
'q' => kVK_ANSI_Q,
'r' => kVK_ANSI_R,
's' => kVK_ANSI_S,
't' => kVK_ANSI_T,
'u' => kVK_ANSI_U,
'v' => kVK_ANSI_V,
'w' => kVK_ANSI_W,
'x' => kVK_ANSI_X,
'y' => kVK_ANSI_Y,
'z' => kVK_ANSI_Z,
'0' => kVK_ANSI_0,
'1' => kVK_ANSI_1,
'2' => kVK_ANSI_2,
'3' => kVK_ANSI_3,
'4' => kVK_ANSI_4,
'5' => kVK_ANSI_5,
'6' => kVK_ANSI_6,
'7' => kVK_ANSI_7,
'8' => kVK_ANSI_8,
'9' => kVK_ANSI_9,
'-' => kVK_ANSI_Minus,
'=' => kVK_ANSI_Equal,
'[' => kVK_ANSI_LeftBracket,
']' => kVK_ANSI_RightBracket,
'\\' => kVK_ANSI_Backslash,
';' => kVK_ANSI_Semicolon,
'\'' => kVK_ANSI_Quote,
',' => kVK_ANSI_Comma,
'.' => kVK_ANSI_Period,
'/' => kVK_ANSI_Slash,
'`' => kVK_ANSI_Grave,
_ => 0,
}
unsafe { CFStringCreateWithCharacters(kCFAllocatorDefault, &chars, 1) }
}
}
#[inline]
unsafe fn get_string(cf_string: CFStringRef) -> Option<String> {
if !cf_string.is_null() {
let mut buf: [i8; 255] = [0; 255];
let success = CFStringGetCString(
cf_string,
buf.as_mut_ptr(),
buf.len() as _,
kCFStringEncodingUTF8,
);
if success != 0 {
let name: &CStr = CStr::from_ptr(buf.as_ptr());
if let Ok(name) = name.to_str() {
return Some(name.to_string());
}
}
}
None
}
#[inline]
unsafe fn get_layout() -> (TISInputSourceRef, *const u8) {
let mut keyboard = TISCopyCurrentKeyboardInputSource();
let mut layout = null_mut();
if !keyboard.is_null() {
layout = TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData);
}
if layout.is_null() {
if !keyboard.is_null() {
CFRelease(keyboard);
}
// https://github.com/microsoft/vscode/issues/23833
keyboard = TISCopyCurrentKeyboardLayoutInputSource();
if !keyboard.is_null() {
layout = TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData);
}
}
if layout.is_null() {
if !keyboard.is_null() {
CFRelease(keyboard);
}
keyboard = TISCopyCurrentASCIICapableKeyboardLayoutInputSource();
if !keyboard.is_null() {
layout = TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData);
}
}
if layout.is_null() {
if !keyboard.is_null() {
CFRelease(keyboard);
}
return (null_mut(), null_mut());
}
let layout_ptr = CFDataGetBytePtr(layout as _);
if layout_ptr.is_null() {
if !keyboard.is_null() {
CFRelease(keyboard);
}
return (null_mut(), null_mut());
}
(keyboard, layout_ptr)
}
#[inline]
fn get_map(name: &str, layout: *const u8) -> Map<char, CGKeyCode> {
log::info!("Create keyboard map for {}", name);
let mut keys_down: u32 = 0;
let mut map = Map::new();
for keycode in 0..128 {
let mut buff = [0_u16; BUF_LEN];
let kb_type = unsafe { LMGetKbdType() };
let mut length: UniCharCount = 0;
let _retval = unsafe {
UCKeyTranslate(
layout,
keycode,
kUCKeyActionDisplay as _,
0,
kb_type as _,
kUCKeyTranslateDeadKeysBit as _,
&mut keys_down,
BUF_LEN,
&mut length,
&mut buff,
)
};
if length > 0 {
if let Ok(str) = String::from_utf16(&buff[..length]) {
if let Some(chr) = str.chars().next() {
map.insert(chr, keycode as _);
}
}
}
}
map
}
unsafe impl Send for Enigo {}

View File

@@ -1,4 +1,7 @@
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731
//
// JP/KR mapping https://github.com/TigerVNC/tigervnc/blob/1a008c1380305648ab50f1d99e73439747e9d61d/vncviewer/win32.c#L267
// altgr handle: https://github.com/TigerVNC/tigervnc/blob/dccb95f345f7a9c5aa785a19d1bfa3fdecd8f8e0/vncviewer/Viewport.cxx#L1066
pub const EVK_RETURN: u16 = 0x0D;
pub const EVK_TAB: u16 = 0x09;
@@ -7,9 +10,14 @@ pub const EVK_BACK: u16 = 0x08;
pub const EVK_ESCAPE: u16 = 0x1b;
pub const EVK_LWIN: u16 = 0x5b;
pub const EVK_SHIFT: u16 = 0x10;
//pub const EVK_LSHIFT: u16 = 0xa0;
pub const EVK_RSHIFT: u16 = 0xa1;
//pub const EVK_LMENU: u16 = 0xa4;
pub const EVK_RMENU: u16 = 0xa5;
pub const EVK_CAPITAL: u16 = 0x14;
pub const EVK_MENU: u16 = 0x12;
pub const EVK_LCONTROL: u16 = 0xa2;
pub const EVK_RCONTROL: u16 = 0xa3;
pub const EVK_HOME: u16 = 0x24;
pub const EVK_PRIOR: u16 = 0x21;
pub const EVK_NEXT: u16 = 0x22;

View File

@@ -16,6 +16,7 @@ extern "system" {
/// The main struct for handling the event emitting
#[derive(Default)]
pub struct Enigo;
static mut LAYOUT: HKL = std::ptr::null_mut();
fn mouse_event(flags: u32, data: u32, dx: i32, dy: i32) -> DWORD {
let mut input = INPUT {
@@ -35,6 +36,18 @@ fn mouse_event(flags: u32, data: u32, dx: i32, dy: i32) -> DWORD {
}
fn keybd_event(flags: u32, vk: u16, scan: u16) -> DWORD {
let mut scan = scan;
unsafe {
// https://github.com/rustdesk/rustdesk/issues/366
if scan == 0 {
if LAYOUT.is_null() {
let current_window_thread_id =
GetWindowThreadProcessId(GetForegroundWindow(), std::ptr::null_mut());
LAYOUT = GetKeyboardLayout(current_window_thread_id);
}
scan = MapVirtualKeyExW(vk as _, 0, LAYOUT) as _;
}
}
let mut input = INPUT {
type_: INPUT_KEYBOARD,
u: unsafe {
@@ -176,13 +189,13 @@ impl KeyboardControllable for Enigo {
}
fn key_click(&mut self, key: Key) {
let scancode = self.key_to_scancode(key);
keybd_event(KEYEVENTF_SCANCODE, 0, scancode);
keybd_event(KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE, 0, scancode);
let vk = self.key_to_keycode(key);
keybd_event(0, vk, 0);
keybd_event(KEYEVENTF_KEYUP, vk, 0);
}
fn key_down(&mut self, key: Key) -> crate::ResultType {
let res = keybd_event(KEYEVENTF_SCANCODE, 0, self.key_to_scancode(key));
let res = keybd_event(0, self.key_to_keycode(key), 0);
if res == 0 {
let err = get_error();
if !err.is_empty() {
@@ -193,11 +206,7 @@ impl KeyboardControllable for Enigo {
}
fn key_up(&mut self, key: Key) {
keybd_event(
KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE,
0,
self.key_to_scancode(key),
);
keybd_event(KEYEVENTF_KEYUP, self.key_to_keycode(key), 0);
}
fn get_key_state(&mut self, key: Key) -> bool {
@@ -257,6 +266,9 @@ impl Enigo {
}
fn key_to_keycode(&self, key: Key) -> u16 {
unsafe {
LAYOUT = std::ptr::null_mut();
}
// do not use the codes from crate winapi they're
// wrongly typed with i32 instead of i16 use the
// ones provided by win/keycodes.rs that are prefixed
@@ -307,7 +319,6 @@ impl Enigo {
Key::Numpad9 => EVK_NUMPAD9,
Key::Cancel => EVK_CANCEL,
Key::Clear => EVK_CLEAR,
Key::Menu => EVK_MENU,
Key::Pause => EVK_PAUSE,
Key::Kana => EVK_KANA,
Key::Hangul => EVK_HANGUL,
@@ -338,6 +349,9 @@ impl Enigo {
Key::Divide => EVK_DIVIDE,
Key::NumpadEnter => EVK_RETURN,
Key::Equals => '=' as _,
Key::RightShift => EVK_RSHIFT,
Key::RightControl => EVK_RCONTROL,
Key::RightAlt => EVK_RMENU,
Key::Raw(raw_keycode) => raw_keycode,
Key::Layout(c) => self.get_layoutdependent_keycode(c.to_string()),
@@ -345,19 +359,17 @@ impl Enigo {
}
}
fn key_to_scancode(&self, key: Key) -> u16 {
let keycode = self.key_to_keycode(key);
unsafe { MapVirtualKeyW(keycode as u32, 0) as u16 }
}
fn get_layoutdependent_keycode(&self, string: String) -> u16 {
// get the first char from the string ignore the rest
// ensure its not a multybyte char
if let Some(chr) = string.chars().nth(0) {
// NOTE VkKeyScanW uses the current keyboard layout
// to specify a layout use VkKeyScanExW and GetKeyboardLayout
// NOTE VkKeyScanW uses the current keyboard LAYOUT
// to specify a LAYOUT use VkKeyScanExW and GetKeyboardLayout
// or load one with LoadKeyboardLayoutW
let keycode_and_shiftstate = unsafe { VkKeyScanW(chr as _) };
let current_window_thread_id =
unsafe { GetWindowThreadProcessId(GetForegroundWindow(), std::ptr::null_mut()) };
unsafe { LAYOUT = GetKeyboardLayout(current_window_thread_id) };
let keycode_and_shiftstate = unsafe { VkKeyScanExW(chr as _, LAYOUT) };
keycode_and_shiftstate as _
} else {
0

View File

@@ -7,20 +7,20 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
protobuf = { version = "3.0.0-pre", git = "https://github.com/stepancheg/rust-protobuf" }
tokio = { version = "0.2", features = ["full"] }
tokio-util = { version = "0.3", features = ["full"] }
protobuf = "3.0.0-alpha.2"
tokio = { version = "1.15", features = ["full"] }
tokio-util = { version = "0.6", features = ["full"] }
futures = "0.3"
bytes = "0.5"
bytes = "1.1"
log = "0.4"
env_logger = "0.8"
env_logger = "0.9"
socket2 = { version = "0.3", features = ["reuseport"] }
zstd = "0.5"
quinn = {version = "0.6", optional = true }
zstd = "0.9"
quinn = {version = "0.8", optional = true }
anyhow = "1.0"
futures-util = "0.3"
directories-next = "2.0"
rand = "0.7"
rand = "0.8"
serde_derive = "1.0"
serde = "1.0"
lazy_static = "1.4"
@@ -28,6 +28,8 @@ confy = { git = "https://github.com/open-trade/confy" }
dirs-next = "2.0"
filetime = "0.2"
sodiumoxide = "0.2"
regex = "1.4"
tokio-socks = { git = "https://github.com/open-trade/tokio-socks" }
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
mac_address = "1.1"
@@ -36,7 +38,7 @@ mac_address = "1.1"
quic = ["quinn"]
[build-dependencies]
protobuf-codegen-pure = { version = "3.0.0-pre", git = "https://github.com/stepancheg/rust-protobuf" }
protobuf-codegen-pure = "3.0.0-alpha.2"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3", features = ["winuser"] }

View File

@@ -25,6 +25,11 @@ message VideoFrame {
}
}
message IdPk {
string id = 1;
bytes pk = 2;
}
message DisplayInfo {
sint32 x = 1;
sint32 y = 2;
@@ -54,6 +59,7 @@ message LoginRequest {
FileTransfer file_transfer = 7;
PortForward port_forward = 8;
}
bool video_ack_required = 9;
}
message ChatMessage { string text = 1; }
@@ -83,6 +89,7 @@ message MouseEvent {
}
enum ControlKey {
Unknown = 0;
Alt = 1;
Backspace = 2;
CapsLock = 3;
@@ -108,7 +115,7 @@ enum ControlKey {
/// meta key (also known as "windows"; "super"; and "command")
Meta = 23;
/// option key on macOS (alt key on Linux and Windows)
Option = 24;
Option = 24; // deprecated, use Alt instead
PageDown = 25;
PageUp = 26;
Return = 27;
@@ -129,7 +136,7 @@ enum ControlKey {
Numpad9 = 42;
Cancel = 43;
Clear = 44;
Menu = 45;
Menu = 45; // deprecated, use Alt instead
Pause = 46;
Kana = 47;
Hangul = 48;
@@ -157,6 +164,9 @@ enum ControlKey {
Divide = 70;
Equals = 71;
NumpadEnter = 72;
RShift = 73;
RControl = 74;
RAlt = 75;
CtrlAltDel = 100;
LockScreen = 101;
}
@@ -190,15 +200,15 @@ message CursorPosition {
message Hash {
string salt = 1;
string challenge = 2;
};
}
message Clipboard {
bool compress = 1;
bytes content = 2;
};
}
enum FileType {
Dir = 1;
Dir = 0;
DirLink = 2;
DirDrive = 3;
File = 4;
@@ -301,6 +311,69 @@ message FileDirCreate {
string path = 2;
}
// main logic from freeRDP
message CliprdrMonitorReady {
int32 conn_id = 1;
}
message CliprdrFormat {
int32 conn_id = 1;
int32 id = 2;
string format = 3;
}
message CliprdrServerFormatList {
int32 conn_id = 1;
repeated CliprdrFormat formats = 2;
}
message CliprdrServerFormatListResponse {
int32 conn_id = 1;
int32 msg_flags = 2;
}
message CliprdrServerFormatDataRequest {
int32 conn_id = 1;
int32 requested_format_id = 2;
}
message CliprdrServerFormatDataResponse {
int32 conn_id = 1;
int32 msg_flags = 2;
bytes format_data = 3;
}
message CliprdrFileContentsRequest {
int32 conn_id = 1;
int32 stream_id = 2;
int32 list_index = 3;
int32 dw_flags = 4;
int32 n_position_low = 5;
int32 n_position_high = 6;
int32 cb_requested = 7;
bool have_clip_data_id = 8;
int32 clip_data_id = 9;
}
message CliprdrFileContentsResponse {
int32 conn_id = 1;
int32 msg_flags = 3;
int32 stream_id = 4;
bytes requested_data = 5;
}
message Cliprdr {
oneof union {
CliprdrMonitorReady ready = 1;
CliprdrServerFormatList format_list = 2;
CliprdrServerFormatListResponse format_list_response = 3;
CliprdrServerFormatDataRequest format_data_request = 4;
CliprdrServerFormatDataResponse format_data_response = 5;
CliprdrFileContentsRequest file_contents_request = 6;
CliprdrFileContentsResponse file_contents_response = 7;
}
}
message SwitchDisplay {
int32 display = 1;
sint32 x = 2;
@@ -309,13 +382,14 @@ message SwitchDisplay {
int32 height = 5;
}
enum Permission {
Keyboard = 1;
Clipboard = 2;
Audio = 3;
}
message PermissionInfo {
enum Permission {
Keyboard = 0;
Clipboard = 2;
Audio = 3;
File = 4;
}
Permission permission = 1;
bool enabled = 2;
}
@@ -327,13 +401,12 @@ enum ImageQuality {
Best = 4;
}
enum BoolOption {
NotSet = 0;
No = 1;
Yes = 2;
}
message OptionMessage {
enum BoolOption {
NotSet = 0;
No = 1;
Yes = 2;
}
ImageQuality image_quality = 1;
BoolOption lock_after_session_end = 2;
BoolOption show_remote_cursor = 3;
@@ -342,6 +415,12 @@ message OptionMessage {
int32 custom_image_quality = 6;
BoolOption disable_audio = 7;
BoolOption disable_clipboard = 8;
BoolOption enable_file_transfer = 9;
}
message OptionResponse {
OptionMessage opt = 1;
string error = 2;
}
message TestDelay {
@@ -354,10 +433,7 @@ message PublicKey {
bytes symmetric_value = 2;
}
message SignedId {
bytes id = 1;
bytes pk = 2;
}
message SignedId { bytes id = 1; }
message AudioFormat {
uint32 sample_rate = 1;
@@ -375,6 +451,8 @@ message Misc {
AudioFormat audio_format = 8;
string close_reason = 9;
bool refresh_video = 10;
OptionResponse option_response = 11;
bool video_received = 12;
}
}
@@ -397,5 +475,6 @@ message Message {
FileAction file_action = 17;
FileResponse file_response = 18;
Misc misc = 19;
Cliprdr cliprdr = 20;
}
}

View File

@@ -6,11 +6,19 @@ message RegisterPeer {
int32 serial = 2;
}
enum ConnType {
DEFAULT_CONN = 0;
FILE_TRANSFER = 1;
PORT_FORWARD = 2;
RDP = 3;
}
message RegisterPeerResponse { bool request_pk = 2; }
message PunchHoleRequest {
string id = 1;
NatType nat_type = 2;
ConnType conn_type = 4;
}
message PunchHole {
@@ -40,6 +48,7 @@ message PunchHoleSent {
string id = 2;
string relay_server = 3;
NatType nat_type = 4;
string version = 5;
}
message RegisterPk {
@@ -50,8 +59,13 @@ message RegisterPk {
message RegisterPkResponse {
enum Result {
OK = 1;
OK = 0;
UUID_MISMATCH = 2;
ID_EXISTS = 3;
TOO_FREQUENT = 4;
INVALID_ID_FORMAT = 5;
NOT_SUPPORT = 6;
SERVER_ERROR = 7;
}
Result result = 1;
}
@@ -60,8 +74,10 @@ message PunchHoleResponse {
bytes socket_addr = 1;
bytes pk = 2;
enum Failure {
ID_NOT_EXIST = 1;
ID_NOT_EXIST = 0;
OFFLINE = 2;
LICENSE_MISMATCH = 3;
LICENSE_OVERUSE = 4;
}
Failure failure = 3;
string relay_server = 4;
@@ -69,6 +85,7 @@ message PunchHoleResponse {
NatType nat_type = 5;
bool is_local = 6;
}
string other_failure = 7;
}
message ConfigUpdate {
@@ -82,6 +99,7 @@ message RequestRelay {
bytes socket_addr = 3;
string relay_server = 4;
bool secure = 5;
ConnType conn_type = 7;
}
message RelayResponse {
@@ -92,6 +110,8 @@ message RelayResponse {
string id = 4;
bytes pk = 5;
}
string refuse_reason = 6;
string version = 7;
}
message SoftwareUpdate { string url = 1; }
@@ -109,6 +129,18 @@ message LocalAddr {
bytes socket_addr = 1;
bytes local_addr = 2;
string relay_server = 3;
string id = 4;
string version = 5;
}
message PeerDiscovery {
string cmd = 1;
string mac = 2;
string id = 3;
string username = 4;
string hostname = 5;
string platform = 6;
string misc = 7;
}
message RendezvousMessage {
@@ -129,5 +161,6 @@ message RendezvousMessage {
RelayResponse relay_response = 19;
TestNatRequest test_nat_request = 20;
TestNatResponse test_nat_response = 21;
PeerDiscovery peer_discovery = 22;
}
}

View File

@@ -6,26 +6,23 @@ use sodiumoxide::crypto::sign;
use std::{
collections::HashMap,
fs,
net::SocketAddr,
net::{IpAddr, Ipv4Addr, SocketAddr},
path::{Path, PathBuf},
sync::{Arc, Mutex, RwLock},
time::SystemTime,
};
pub const APP_NAME: &str = "RustDesk";
pub const BIND_INTERFACE: &str = "0.0.0.0";
pub const RENDEZVOUS_TIMEOUT: u64 = 12_000;
pub const CONNECT_TIMEOUT: u64 = 18_000;
pub const REG_INTERVAL: i64 = 12_000;
pub const COMPRESS_LEVEL: i32 = 3;
const SERIAL: i32 = 0;
const SERIAL: i32 = 1;
// 128x128
#[cfg(target_os = "macos")] // 128x128 on 160x160 canvas, then shrink to 128, mac looks better with padding
pub const ICON: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAyVBMVEUAAAAAcf8Acf8Acf8Acv8Acf8Acf8Acf8Acf8AcP8Acf8Ab/8AcP8Acf////8AaP/z+f/o8v/k7v/5/v/T5f8AYP/u9v/X6f+hx/+Kuv95pP8Aef/B1/+TwP9xoP8BdP/g6P+Irv9ZmP8Bgf/E3f98q/9sn/+01f+Es/9nm/9Jif8hhv8off/M4P+syP+avP86iP/c7f+xy/9yqf9Om/9hk/9Rjv+60P99tv9fpf88lv8yjf8Tgf8deP+kvP8BiP8NeP8hkP80gP8oj2VLAAAADXRSTlMA7o7qLvnaxZ1FOxYPjH9HWgAABHJJREFUeNrtm+tW4jAQgBfwuu7MtIUWsOUiCCioIIgLiqvr+z/UHq/LJKVkmwTcc/r9E2nzlU4mSTP9lpGRkZGR8VX5cZjfL+yCEXYL+/nDH//U/Pd8DgyTy39Xbv7oIAcWyB0cqbW/sweW2NtRaj8H1sgpGOwUIAH7Bkd7YJW9dXFwAJY5WNP/cmCZQnJvzIN18on5LwfWySXlxEPYAIcad8D6PdiHDbCfIFCADVBIENiFDbCbIACKPPXrZ+cP8E6/0znvP4EymgIEravIRcTxu8HxNSJ60a8W0AYECKrlAN+YwAthCd9wm1Ug6wKzIn5SgRduXfwkqDasCjx0XFzi9PV6zwNcIuhcWBOg+ikySq8C9UD4dEKWBCoOcspvAuLHTo9sCDQiFPHotRM48j8G5gVur1FdAN2uaYEuiz7xFsgEJ2RUoMUakXuBTHHoGxQYOBhHjeUBAefEnMAowFhaLBOKuOemBBbxLRQrH2PBCgMvNCPQGMeevTb9zLrPxz2Mo+QbEaijzPUcOOHMQZkKGRAIPem39+bypREMPTkQW/oCfk866zAkiIFG4yIKRE/aAnfiSd0WrORY6pFdXQEqi9mvAQm0RIOSnoCcZ8vJoz3diCnjRk+g8VP4/fuQDJ2Lxr6WwG0gXs9aTpDzW0vgDBlVUpixR8gYk44AD8FrUKHr8JQJGgIDnoDqoALxmWPQSi9AVVzm8gKUuEPGr/QCvptwJkbSYT/TC4S8C96DGjTj86aHtAI0x2WaBIq0eSYYpRa4EsdWVVwWu9O0Aj6f6dyBMnwEraeOgSYu0wZlauzA47QCbT7DgAQSE+hZWoEBF/BBmWOewNMK3BsSqKUW4MGcWqCSVmDkbvkXGKQOwg6PAUO9oL3xXhA20yaiCjuwYygRVQlUOTWTCf2SuNJTxeFjgaHByGuAIvd8ItdPLTDhS7IuqEE1YSKVOgbayLhSFQhMzYh8hwfBs1r7c505YVIQYEdNoKwxK06MJiyrpUFHiF0NAfCQUVHoiRclIXJIR6C2fqG37pBHvcWpgwzvAtYwkR5UGV2e42UISdBJETl3mg8ouo54Rcnti1/vaT+iuUQBt500Cgo4U10BeHSkk57FB0JjWkKRMWgLUA0lLodtImAQdaMiiri3+gIAPZQoutHNsgKF1aaDMhMyIdBf8Th+Bh8MTjGWCpl5Wv43tDmnF+IUVMrcZgRoiAxhtrloYizNkZaAnF5leglbNhj0wYCAbCDvGb0mP4nib7O7ZlcYQ2m1gPtIZgVgGNNMeaVAaWR+57TrqgtUnm3sHQ+kYeE6fufUubG1ez50FXbPnWgBlgSABmN3TTcsRl2yWkHRrwbiunvk/W2+Mg1hPZplPDeXRbZzStFH15s1QIVd3UImP5z/bHpeeQLvRJ7XLFUffQIlCvqlXETQbgN9/rlYABGosv+Vi9m2Xs639YLGrZd0br+odetlvdsvbN56abfd4vbCzv9Q3v/ygoOV21A4OPpfXvH4Ai+5ZGRkZGRkbJA/t/I0QMzoMiEAAAAASUVORK5CYII=
";
#[cfg(windows)] // windows, 32x32, bigger very ugly after shrink
pub const ICON: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAolBMVEUAAAAAcf8Acf8Acf8AcP8Acf8Acf8Acf8AcP8Acf/////9/v/7/f+gyv9wr/8Ld/8GdP/A3P+nzv+Qwf9mqv8lhv8UfP+Kvv88k/8zjv/x+P/Y6f/U5//J4f/F3/+x1P+pz/+izP+Cuv9Zov9Qnv9FmP8gg//f7f+42P96tv9fpv8ui//1+f/q8//o8v/Q5f+ax/+Zxv+VxP+Fu/9rrf8rif+x1o3FAAAACXRSTlMAv/RPTPKHioRsIqhAAAABNklEQVQ4y4WT6XaCQAyFB7S2GUD2RaxSKGDV7sv7v1on4djEluL9Ncn5biaZk1FKzSwbRmVbM2V0DRNaGD9Maq6sacBS9jRwpUTw1Ww7SEOvkwQDaeVofQeJ1nrXjgD3pTaqCDCg/xs4OBrlwUGTHvxzoHAx69Y9+Hk5oGdAsCNXSoHfEN1JYEme4KcfvO9WAmtMBNx6jIaCgSPGLbAyvKRhAEcrAxAKTSZiACu+gNSbyWwZeKdQKj91yRXWIOWZTMgATun6EtjgczNQaKMEWD0+xJ6B4AnvECVqdKwYoJ50hIPyw25AANkzpsLB00cYOIUEoHU0uVaQVcMxBwlgVZJ3Orz+3ahH6gP2tBgfYzsZmdo1fGIzRx5Irn2WxKaHeJnKtb/4cS5/PbWACd0oo/n/39/4vwGFYSxtSYV4OAAAAABJRU5ErkJggg==
";
#[cfg(target_os = "linux")] // 128x128 no padding
#[cfg(not(target_os = "macos"))] // 128x128 no padding
pub const ICON: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAA7VBMVEUAAAAAcf8Acf8Acf8Adf8Acf8Acf8AcP8Acv8AcP8Acf8Acf8Acf8Acv8Acf8Acf8Ab/8AcP8Acf8Acf8Acf/////7/f8Dc/8TfP/1+f/n8v9Hmf/u9v+Uw//Q5f9hp/8Yfv8Qev8Ld/+52P+z1f+s0f81j/8wjP8Hdf/3+/8mh/8fg//x9//h7//H4P9xsP9rrf9oq/8rif/r9P/D3v+92/+Duv9bpP/d7f/U5/9NnP8/lP8jhP/L4v/B3P+OwP9+t/95tf9Rn/8bgf/Z6v+Zx/90sv9lqf85kf+hy/9UoP+Wxf+kzP+dyP+Lvv/H4q8IAAAAFHRSTlMA+u6bB6x5XR4V0+S4i4k5N+a81W8MiAQAAAVcSURBVHjazdvpWtpAGIbhgEutdW3fL2GHsMsiq4KI+66t5384XahF/GbizJAy3j/1Ah5CJhNCxpm1vbryLRrBfxKJrq+sbjtSa5u7WIDdzTVH5PNSBAsSWfrsMJ+iWKDoJ2fW8hIWbGl55vW/YuE2XhUsb8CCr9OCJVix9G//gyWf/o6/KCyJfrbwAfAPYS0CayK/j4mbsGjrV8AXWLTrONuwasdZhVWrzgqsWnG+wap1Jwqrok4EVkUcmKhdVvBaOVnzYEY/oJpMD4mo6ONF/ZSIUsX2FZjQA7xRqUET+y/v2W/Sy59u62DCDMgdJmhqgIk7eqWQBBNWwPhmj147w8QTzTjKVsGEEBBLuzSrhIkivTF8DD/Aa6forQNMHBD/VyXkgHGfuBN5ALln1TADOnESyGCiT8L/1kILqD6Q0BEm9kkofhdSwNUJiV1jQvZ/SnthBNSaJJGZbgGJUnX+gEqCZPpsJ2T2Y/MGVBrE8eOAvCA/X8A4QXLnmEhTgIPqPAG5IQU4fhmkFOT7HAFenwIU8Jd/TUEODQIUtu1eOj/dUD9cknOTpgEDkup3YrOfVStDUomcWcBVisTiNxVw3TPpgCl4RgFFybZ/9iHmn8uS2yYBA8m7qUEu9oOEejH9gHxC+PazCHbcFM8K+gGHJNAs4z2xgnAkVHQDcnG1IzvnCSfvom7AM3EZ9voah4+KXoAvGFJHMSgqEfegF3BBTKoOVfkMMXFfJ8AT7MuXUDeOE9PWCUiKBpKOlmAP1gngH2LChw7vhJgr9YD8Hnt0BxrE27CtHnDJR4AHTX1+KFAP4Ef0LHTxN9HwlAMSbAjmoavKZ8ayakDXYAhwN3wzqgZk2UPvwRjshmeqATeCT09f3mWnEqoBGf4NxAB/moRqADuOtmDiid6KqQVcsQeOYOKW3uqqBRwL5nITj/yrlFpAVrDpTJT5llQLaLMHwshY7UDgvD+VujDC96WWWsBtSAE5FnChFnAeUkDMdAvw88EqTNT5SYXpTlgPaRQM1AIGorkolNnoUS1gJHigCX48SaoF3Asuspg4Mz0U8+FTgIkCG01V09kwBQP8xG5ofD5AXeirkPEJSUlwSVIfP5ykVQNaggvz+k7prTvVgDKF8BnUXP4kqgEe/257E8Ig7EE1gA8g2stBTz7FLxqrB3SIeYaeQ2IG6gE5l2+Cmt5MGOfP4KsGiH8DOYWOoujnDY2ALHF3810goZFOQDVBTFx9Uj7eI6bp6QTgnLjeGGq6KeJuoRUQixN3pDYWyz1Rva8XIL5UPFQZCsmG3gV7R+dieS+Jd3iHLglce7oBuCOhp3zwHLxPQpfQDvBOSKjZqUIml3ZJ6AD6AajFSZJwewWR8ZPsEY26SQDaJOMeZP23w6bTJ6kBjAJQILm9hzqm7otu4G+nhgGxIQUlPLKzL7GhbxqAboMCuN2XXd+lAL0ajAMwclV+FD6jAPEy5ghAlhfwX2FODX445gHKxyN++fs64PUHmDMAbbYN2DlKk2QaScwdgMs4SZxMv4OJJSoIIQBl2Qtk3gk4qiOUANRPJQHB+0A6j5AC4J27QQEZ4eZPAsYBXFk0N/YD7iUrxRBqALxOTzoMC3x8lCFlfkMjuz8iLfk6fzQCQgjg8q3ZEd8RzUVuKelBh96Nzcc3qelL1V+2zfRv1xc56Ino3tpdPT7cd//MspfTrD/7R6p4W4O2qLMObfnyIHvvYcrPtkZjDybW7d/eb32Bg/UlHnYXuXz5CMt8rC90sr7Uy/5iN+vL/ewveLS/5NNKwcbyR1r2a3/h8wdY+v3L2tZC5oUvW2uO1M7qyvp/Xv6/48z4CTxjJEfyjEaMAAAAAElFTkSuQmCC
";
#[cfg(target_os = "macos")]
@@ -36,6 +33,7 @@ type Size = (i32, i32, i32, i32);
lazy_static::lazy_static! {
static ref CONFIG: Arc<RwLock<Config>> = Arc::new(RwLock::new(Config::load()));
static ref CONFIG2: Arc<RwLock<Config2>> = Arc::new(RwLock::new(Config2::load()));
static ref LOCAL_CONFIG: Arc<RwLock<LocalConfig>> = Arc::new(RwLock::new(LocalConfig::load()));
pub static ref ONLINE: Arc<Mutex<HashMap<String, i64>>> = Default::default();
}
#[cfg(any(target_os = "android", target_os = "ios"))]
@@ -48,13 +46,20 @@ const CHARS: &'static [char] = &[
];
pub const RENDEZVOUS_SERVERS: &'static [&'static str] = &[
"rs-ny.rustdesk.com",
"rs-sg.rustdesk.com",
"rs-cn.rustdesk.com",
];
pub const RENDEZVOUS_PORT: i32 = 21116;
pub const RELAY_PORT: i32 = 21117;
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum NetworkType {
Direct,
ProxySocks,
}
#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub struct Config {
#[serde(default)]
id: String,
@@ -70,13 +75,19 @@ pub struct Config {
keys_confirmed: HashMap<String, bool>,
}
#[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)]
pub struct Socks5Server {
#[serde(default)]
pub proxy: String,
#[serde(default)]
pub username: String,
#[serde(default)]
pub password: String,
}
// more variable configs
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub struct Config2 {
#[serde(default)]
remote_id: String, // latest used one
#[serde(default)]
size: Size,
#[serde(default)]
rendezvous_server: String,
#[serde(default)]
@@ -84,6 +95,9 @@ pub struct Config2 {
#[serde(default)]
serial: i32,
#[serde(default)]
socks: Option<Socks5Server>,
// the other scalar value must before this
#[serde(default)]
pub options: HashMap<String, String>,
@@ -119,6 +133,8 @@ pub struct PeerConfig {
pub disable_audio: bool,
#[serde(default)]
pub disable_clipboard: bool,
#[serde(default)]
pub enable_file_transfer: bool,
// the other scalar value must before this
#[serde(default)]
@@ -148,6 +164,20 @@ fn patch(path: PathBuf) -> PathBuf {
.into();
#[cfg(target_os = "macos")]
return _tmp.replace("Application Support", "Preferences").into();
#[cfg(target_os = "linux")]
{
if _tmp == "/root" {
if let Ok(output) = std::process::Command::new("whoami").output() {
let user = String::from_utf8_lossy(&output.stdout)
.to_string()
.trim()
.to_owned();
if user != "root" {
return format!("/home/{}", user).into();
}
}
}
}
}
path
}
@@ -157,9 +187,23 @@ impl Config2 {
Config::load_::<Config2>("2")
}
pub fn file() -> PathBuf {
Config::file_("2")
}
fn store(&self) {
Config::store_(self, "2");
}
pub fn get() -> Config2 {
return CONFIG2.read().unwrap().clone();
}
pub fn set(cfg: Config2) {
let mut lock = CONFIG2.write().unwrap();
*lock = cfg;
lock.store();
}
}
impl Config {
@@ -239,7 +283,7 @@ impl Config {
}
}
fn path<P: AsRef<Path>>(p: P) -> PathBuf {
pub fn path<P: AsRef<Path>>(p: P) -> PathBuf {
#[cfg(any(target_os = "android", target_os = "ios"))]
{
let mut path: PathBuf = APP_DIR.read().unwrap().clone().into();
@@ -259,6 +303,7 @@ impl Config {
return "".into();
}
#[allow(unreachable_code)]
pub fn log_path() -> PathBuf {
#[cfg(target_os = "macos")]
{
@@ -269,11 +314,10 @@ impl Config {
}
#[cfg(target_os = "linux")]
{
if let Some(path) = dirs_next::home_dir().as_mut() {
path.push(format!(".local/share/logs/{}", APP_NAME));
std::fs::create_dir_all(&path).ok();
return path.clone();
}
let mut path = Self::get_home();
path.push(format!(".local/share/logs/{}", APP_NAME));
std::fs::create_dir_all(&path).ok();
return path;
}
if let Some(path) = Self::path("").parent() {
let mut path: PathBuf = path.into();
@@ -312,10 +356,10 @@ impl Config {
#[inline]
pub fn get_any_listen_addr() -> SocketAddr {
format!("{}:0", BIND_INTERFACE).parse().unwrap()
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0)
}
pub fn get_rendezvous_server() -> SocketAddr {
pub fn get_rendezvous_server() -> String {
let mut rendezvous_server = Self::get_option("custom-rendezvous-server");
if rendezvous_server.is_empty() {
rendezvous_server = CONFIG2.write().unwrap().rendezvous_server.clone();
@@ -329,11 +373,7 @@ impl Config {
if !rendezvous_server.contains(":") {
rendezvous_server = format!("{}:{}", rendezvous_server, RENDEZVOUS_PORT);
}
if let Ok(addr) = crate::to_socket_addr(&rendezvous_server) {
addr
} else {
Self::get_any_listen_addr()
}
rendezvous_server
}
pub fn get_rendezvous_servers() -> Vec<String> {
@@ -473,6 +513,9 @@ impl Config {
pub fn set_key_pair(pair: (Vec<u8>, Vec<u8>)) {
let mut config = CONFIG.write().unwrap();
if config.key_pair == pair {
return;
}
config.key_pair = pair;
config.store();
}
@@ -505,6 +548,9 @@ impl Config {
pub fn set_options(v: HashMap<String, String>) {
let mut config = CONFIG2.write().unwrap();
if config.options == v {
return;
}
config.options = v;
config.store();
}
@@ -519,9 +565,6 @@ impl Config {
pub fn set_option(k: String, v: String) {
let mut config = CONFIG2.write().unwrap();
if k == "custom-rendezvous-server" {
config.rendezvous_server = "".to_owned();
}
let v2 = if v.is_empty() { None } else { Some(&v) };
if v2 != config.options.get(&k) {
if v2.is_none() {
@@ -537,7 +580,7 @@ impl Config {
// to-do: how about if one ip register a lot of ids?
let id = Self::get_id();
let mut rng = rand::thread_rng();
let new_id = rng.gen_range(1_000_000_000, 2_000_000_000).to_string();
let new_id = rng.gen_range(1_000_000_000..2_000_000_000).to_string();
Config::set_id(&new_id);
log::info!("id updated from {} to {}", id, new_id);
}
@@ -578,31 +621,34 @@ impl Config {
salt
}
pub fn get_size() -> Size {
CONFIG2.read().unwrap().size
}
pub fn set_size(x: i32, y: i32, w: i32, h: i32) {
pub fn set_socks(socks: Option<Socks5Server>) {
let mut config = CONFIG2.write().unwrap();
let size = (x, y, w, h);
if size == config.size || size.2 < 300 || size.3 < 300 {
if config.socks == socks {
return;
}
config.size = size;
config.socks = socks;
config.store();
}
pub fn set_remote_id(remote_id: &str) {
let mut config = CONFIG2.write().unwrap();
if remote_id == config.remote_id {
return;
}
config.remote_id = remote_id.into();
config.store();
pub fn get_socks() -> Option<Socks5Server> {
CONFIG2.read().unwrap().socks.clone()
}
pub fn get_remote_id() -> String {
CONFIG2.read().unwrap().remote_id.clone()
pub fn get_network_type() -> NetworkType {
match &CONFIG2.read().unwrap().socks {
None => NetworkType::Direct,
Some(_) => NetworkType::ProxySocks,
}
}
pub fn get() -> Config {
return CONFIG.read().unwrap().clone();
}
pub fn set(cfg: Config) {
let mut lock = CONFIG.write().unwrap();
*lock = cfg;
lock.store();
}
}
@@ -636,7 +682,7 @@ impl PeerConfig {
Config::path(path).with_extension("toml")
}
pub fn peers() -> Vec<(String, SystemTime, PeerInfoSerde)> {
pub fn peers() -> Vec<(String, SystemTime, PeerConfig)> {
if let Ok(peers) = Config::path(PEERS).read_dir() {
if let Ok(peers) = peers
.map(|res| res.map(|e| e.path()))
@@ -649,21 +695,19 @@ impl PeerConfig {
&& p.extension().map(|p| p.to_str().unwrap_or("")) == Some("toml")
})
.map(|p| {
let t = fs::metadata(p)
.map(|m| m.modified().unwrap_or(SystemTime::UNIX_EPOCH))
.unwrap_or(SystemTime::UNIX_EPOCH);
let t = crate::get_modified_time(&p);
let id = p
.file_stem()
.map(|p| p.to_str().unwrap_or(""))
.unwrap_or("")
.to_owned();
let info = PeerConfig::load(&id).info;
if info.platform.is_empty() {
let c = PeerConfig::load(&id);
if c.info.platform.is_empty() {
fs::remove_file(&p).ok();
}
(id, t, info)
(id, t, c)
})
.filter(|p| !p.2.platform.is_empty())
.filter(|p| !p.2.info.platform.is_empty())
.collect();
peers.sort_unstable_by(|a, b| b.1.cmp(&a.1));
return peers;
@@ -673,6 +717,123 @@ impl PeerConfig {
}
}
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct LocalConfig {
#[serde(default)]
remote_id: String, // latest used one
#[serde(default)]
size: Size,
#[serde(default)]
pub fav: Vec<String>,
#[serde(default)]
options: HashMap<String, String>,
}
impl LocalConfig {
fn load() -> LocalConfig {
Config::load_::<LocalConfig>("_local")
}
fn store(&self) {
Config::store_(self, "_local");
}
pub fn get_size() -> Size {
LOCAL_CONFIG.read().unwrap().size
}
pub fn set_size(x: i32, y: i32, w: i32, h: i32) {
let mut config = LOCAL_CONFIG.write().unwrap();
let size = (x, y, w, h);
if size == config.size || size.2 < 300 || size.3 < 300 {
return;
}
config.size = size;
config.store();
}
pub fn set_remote_id(remote_id: &str) {
let mut config = LOCAL_CONFIG.write().unwrap();
if remote_id == config.remote_id {
return;
}
config.remote_id = remote_id.into();
config.store();
}
pub fn get_remote_id() -> String {
LOCAL_CONFIG.read().unwrap().remote_id.clone()
}
pub fn set_fav(fav: Vec<String>) {
let mut lock = LOCAL_CONFIG.write().unwrap();
if lock.fav == fav {
return;
}
lock.fav = fav;
lock.store();
}
pub fn get_fav() -> Vec<String> {
LOCAL_CONFIG.read().unwrap().fav.clone()
}
pub fn get_option(k: &str) -> String {
if let Some(v) = LOCAL_CONFIG.read().unwrap().options.get(k) {
v.clone()
} else {
"".to_owned()
}
}
pub fn set_option(k: String, v: String) {
let mut config = LOCAL_CONFIG.write().unwrap();
let v2 = if v.is_empty() { None } else { Some(&v) };
if v2 != config.options.get(&k) {
if v2.is_none() {
config.options.remove(&k);
} else {
config.options.insert(k, v);
}
config.store();
}
}
}
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct LanPeers {
#[serde(default)]
pub peers: String,
}
impl LanPeers {
pub fn load() -> LanPeers {
let _ = CONFIG.read().unwrap(); // for lock
match confy::load_path(&Config::file_("_lan_peers")) {
Ok(peers) => peers,
Err(err) => {
log::error!("Failed to load lan peers: {}", err);
Default::default()
}
}
}
pub fn store(peers: String) {
let f = LanPeers { peers };
if let Err(err) = confy::store_path(Config::file_("_lan_peers"), f) {
log::error!("Failed to store lan peers: {}", err);
}
}
pub fn modify_time() -> crate::ResultType<u64> {
let p = Config::file_("_lan_peers");
Ok(fs::metadata(p)?
.modified()?
.duration_since(SystemTime::UNIX_EPOCH)?
.as_millis() as _)
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -7,7 +7,7 @@ use crate::{
};
#[cfg(windows)]
use std::os::windows::prelude::*;
use tokio::{fs::File, prelude::*};
use tokio::{fs::File, io::*};
pub fn read_dir(path: &PathBuf, include_hidden: bool) -> ResultType<FileDirectory> {
let mut dir = FileDirectory {
@@ -193,7 +193,7 @@ pub struct TransferJob {
file: Option<File>,
total_size: u64,
finished_size: u64,
transfered: u64,
transferred: u64,
}
#[inline]
@@ -268,8 +268,8 @@ impl TransferJob {
}
#[inline]
pub fn transfered(&self) -> u64 {
self.transfered
pub fn transferred(&self) -> u64 {
self.transferred
}
#[inline]
@@ -302,7 +302,7 @@ impl TransferJob {
}
}
pub async fn write(&mut self, block: FileTransferBlock) -> ResultType<()> {
pub async fn write(&mut self, block: FileTransferBlock, raw: Option<&[u8]>) -> ResultType<()> {
if block.id != self.id {
bail!("Wrong id");
}
@@ -324,15 +324,20 @@ impl TransferJob {
let path = format!("{}.download", get_string(&path));
self.file = Some(File::create(&path).await?);
}
let data = if let Some(data) = raw {
data
} else {
&block.data
};
if block.compressed {
let tmp = decompress(&block.data);
let tmp = decompress(data);
self.file.as_mut().unwrap().write_all(&tmp).await?;
self.finished_size += tmp.len() as u64;
} else {
self.file.as_mut().unwrap().write_all(&block.data).await?;
self.finished_size += block.data.len() as u64;
self.file.as_mut().unwrap().write_all(data).await?;
self.finished_size += data.len() as u64;
}
self.transfered += block.data.len() as u64;
self.transferred += data.len() as u64;
Ok(())
}
@@ -398,7 +403,7 @@ impl TransferJob {
compressed = true;
}
}
self.transfered += buf.len() as u64;
self.transferred += buf.len() as u64;
}
Ok(Some(FileTransferBlock {
id: self.id,

View File

@@ -6,16 +6,16 @@ pub mod rendezvous_proto;
pub use bytes;
pub use futures;
pub use protobuf;
use socket2::{Domain, Socket, Type};
use std::{
fs::File,
io::{self, BufRead},
net::{Ipv4Addr, SocketAddr, SocketAddrV4, ToSocketAddrs},
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
path::Path,
time::{self, SystemTime, UNIX_EPOCH},
};
pub use tokio;
pub use tokio_util;
pub mod socket_client;
pub mod tcp;
pub mod udp;
pub use env_logger;
@@ -27,7 +27,14 @@ pub use anyhow::{self, bail};
pub use futures_util;
pub mod config;
pub mod fs;
pub use lazy_static;
pub use mac_address;
pub use rand;
pub use regex;
pub use sodiumoxide;
pub use tokio_socks;
pub use tokio_socks::IntoTargetAddr;
pub use tokio_socks::TargetAddr;
#[cfg(feature = "quic")]
pub type Stream = quic::Connection;
@@ -36,7 +43,7 @@ pub type Stream = tcp::FramedStream;
#[inline]
pub async fn sleep(sec: f32) {
tokio::time::delay_for(time::Duration::from_secs_f32(sec)).await;
tokio::time::sleep(time::Duration::from_secs_f32(sec)).await;
}
#[macro_export]
@@ -61,30 +68,6 @@ pub fn timeout<T: std::future::Future>(ms: u64, future: T) -> tokio::time::Timeo
tokio::time::timeout(std::time::Duration::from_millis(ms), future)
}
fn new_socket(addr: SocketAddr, tcp: bool, reuse: bool) -> Result<Socket, std::io::Error> {
let stype = {
if tcp {
Type::stream()
} else {
Type::dgram()
}
};
let socket = match addr {
SocketAddr::V4(..) => Socket::new(Domain::ipv4(), stype, None),
SocketAddr::V6(..) => Socket::new(Domain::ipv6(), stype, None),
}?;
if reuse {
// windows has no reuse_port, but it's reuse_address
// almost equals to unix's reuse_port + reuse_address,
// though may introduce nondeterministic bahavior
#[cfg(unix)]
socket.set_reuse_port(true)?;
socket.set_reuse_address(true)?;
}
socket.bind(&addr.into())?;
Ok(socket)
}
pub type ResultType<F, E = anyhow::Error> = anyhow::Result<F, E>;
/// Certain router and firewalls scan the packet and if they
@@ -100,10 +83,10 @@ impl AddrMangle {
.duration_since(UNIX_EPOCH)
.unwrap()
.as_micros() as u32) as u128;
let ip = u32::from_ne_bytes(addr_v4.ip().octets()) as u128;
let ip = u32::from_le_bytes(addr_v4.ip().octets()) as u128;
let port = addr.port() as u128;
let v = ((ip + tm) << 49) | (tm << 17) | (port + (tm & 0xFFFF));
let bytes = v.to_ne_bytes();
let bytes = v.to_le_bytes();
let mut n_padding = 0;
for i in bytes.iter().rev() {
if i == &0u8 {
@@ -123,9 +106,9 @@ impl AddrMangle {
pub fn decode(bytes: &[u8]) -> SocketAddr {
let mut padded = [0u8; 16];
padded[..bytes.len()].copy_from_slice(&bytes);
let number = u128::from_ne_bytes(padded);
let number = u128::from_le_bytes(padded);
let tm = (number >> 17) & (u32::max_value() as u128);
let ip = (((number >> 49) - tm) as u32).to_ne_bytes();
let ip = (((number >> 49) - tm) as u32).to_le_bytes();
let port = (number & 0xFFFFFF) - (tm & 0xFFFF);
SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]),
@@ -172,14 +155,6 @@ pub fn get_version_from_url(url: &str) -> String {
"".to_owned()
}
pub fn to_socket_addr(host: &str) -> ResultType<SocketAddr> {
let addrs: Vec<SocketAddr> = host.to_socket_addrs()?.collect();
if addrs.is_empty() {
bail!("Failed to solve {}", host);
}
Ok(addrs[0])
}
pub fn gen_version() {
let mut file = File::create("./src/version.rs").unwrap();
for line in read_lines("Cargo.toml").unwrap() {
@@ -204,6 +179,20 @@ where
Ok(io::BufReader::new(file).lines())
}
pub fn get_version_number(v: &str) -> i64 {
let mut n = 0;
for x in v.split(".") {
n = n * 1000 + x.parse::<i64>().unwrap_or(0);
}
n
}
pub fn get_modified_time(path: &std::path::Path) -> SystemTime {
std::fs::metadata(&path)
.map(|m| m.modified().unwrap_or(UNIX_EPOCH))
.unwrap_or(UNIX_EPOCH)
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -0,0 +1,91 @@
use crate::{
config::{Config, NetworkType},
tcp::FramedStream,
udp::FramedSocket,
ResultType,
};
use anyhow::Context;
use std::net::SocketAddr;
use tokio::net::ToSocketAddrs;
use tokio_socks::{IntoTargetAddr, TargetAddr};
fn to_socket_addr(host: &str) -> ResultType<SocketAddr> {
use std::net::ToSocketAddrs;
host.to_socket_addrs()?.next().context("Failed to solve")
}
pub fn get_target_addr(host: &str) -> ResultType<TargetAddr<'static>> {
let addr = match Config::get_network_type() {
NetworkType::Direct => to_socket_addr(&host)?.into_target_addr()?,
NetworkType::ProxySocks => host.into_target_addr()?,
}
.to_owned();
Ok(addr)
}
pub fn test_if_valid_server(host: &str) -> String {
let mut host = host.to_owned();
if !host.contains(":") {
host = format!("{}:{}", host, 0);
}
match Config::get_network_type() {
NetworkType::Direct => match to_socket_addr(&host) {
Err(err) => err.to_string(),
Ok(_) => "".to_owned(),
},
NetworkType::ProxySocks => match &host.into_target_addr() {
Err(err) => err.to_string(),
Ok(_) => "".to_owned(),
},
}
}
pub async fn connect_tcp<'t, T: IntoTargetAddr<'t>>(
target: T,
local: SocketAddr,
ms_timeout: u64,
) -> ResultType<FramedStream> {
let target_addr = target.into_target_addr()?;
if let Some(conf) = Config::get_socks() {
FramedStream::connect(
conf.proxy.as_str(),
target_addr,
local,
conf.username.as_str(),
conf.password.as_str(),
ms_timeout,
)
.await
} else {
let addr = std::net::ToSocketAddrs::to_socket_addrs(&target_addr)?
.next()
.context("Invalid target addr")?;
Ok(FramedStream::new(addr, local, ms_timeout).await?)
}
}
pub async fn new_udp<T: ToSocketAddrs>(local: T, ms_timeout: u64) -> ResultType<FramedSocket> {
match Config::get_socks() {
None => Ok(FramedSocket::new(local).await?),
Some(conf) => {
let socket = FramedSocket::new_proxy(
conf.proxy.as_str(),
local,
conf.username.as_str(),
conf.password.as_str(),
ms_timeout,
)
.await?;
Ok(socket)
}
}
}
pub async fn rebind_udp<T: ToSocketAddrs>(local: T) -> ResultType<Option<FramedSocket>> {
match Config::get_network_type() {
NetworkType::Direct => Ok(Some(FramedSocket::new(local).await?)),
_ => Ok(None),
}
}

View File

@@ -1,22 +1,34 @@
use crate::{bail, bytes_codec::BytesCodec, ResultType};
use bytes::{BufMut, Bytes, BytesMut};
use futures::SinkExt;
use futures::{SinkExt, StreamExt};
use protobuf::Message;
use sodiumoxide::crypto::secretbox::{self, Key, Nonce};
use std::{
io::{Error, ErrorKind},
io::{self, Error, ErrorKind},
net::SocketAddr,
ops::{Deref, DerefMut},
pin::Pin,
task::{Context, Poll},
};
use tokio::{
net::{TcpListener, TcpStream, ToSocketAddrs},
stream::StreamExt,
io::{AsyncRead, AsyncWrite, ReadBuf},
net::{lookup_host, TcpListener, TcpSocket, ToSocketAddrs},
};
use tokio_socks::{tcp::Socks5Stream, IntoTargetAddr, ToProxyAddrs};
use tokio_util::codec::Framed;
pub struct FramedStream(Framed<TcpStream, BytesCodec>, Option<(Key, u64, u64)>);
pub trait TcpStreamTrait: AsyncRead + AsyncWrite + Unpin {}
pub struct DynTcpStream(Box<dyn TcpStreamTrait + Send + Sync>);
pub struct FramedStream(
Framed<DynTcpStream, BytesCodec>,
SocketAddr,
Option<(Key, u64, u64)>,
u64,
);
impl Deref for FramedStream {
type Target = Framed<TcpStream, BytesCodec>;
type Target = Framed<DynTcpStream, BytesCodec>;
fn deref(&self) -> &Self::Target {
&self.0
@@ -29,41 +41,132 @@ impl DerefMut for FramedStream {
}
}
impl Deref for DynTcpStream {
type Target = Box<dyn TcpStreamTrait + Send + Sync>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for DynTcpStream {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
fn new_socket(addr: std::net::SocketAddr, reuse: bool) -> Result<TcpSocket, std::io::Error> {
let socket = match addr {
std::net::SocketAddr::V4(..) => TcpSocket::new_v4()?,
std::net::SocketAddr::V6(..) => TcpSocket::new_v6()?,
};
if reuse {
// windows has no reuse_port, but it's reuse_address
// almost equals to unix's reuse_port + reuse_address,
// though may introduce nondeterministic behavior
#[cfg(unix)]
socket.set_reuseport(true)?;
socket.set_reuseaddr(true)?;
}
socket.bind(addr)?;
Ok(socket)
}
impl FramedStream {
pub async fn new<T: ToSocketAddrs, T2: ToSocketAddrs>(
remote_addr: T,
pub async fn new<T1: ToSocketAddrs, T2: ToSocketAddrs>(
remote_addr: T1,
local_addr: T2,
ms_timeout: u64,
) -> ResultType<Self> {
for local_addr in local_addr.to_socket_addrs().await? {
for remote_addr in remote_addr.to_socket_addrs().await? {
if let Ok(stream) = super::timeout(
for local_addr in lookup_host(&local_addr).await? {
for remote_addr in lookup_host(&remote_addr).await? {
let stream = super::timeout(
ms_timeout,
TcpStream::connect_std(
super::new_socket(local_addr, true, true)?.into_tcp_stream(),
&remote_addr,
),
new_socket(local_addr, true)?.connect(remote_addr),
)
.await?
{
return Ok(Self(Framed::new(stream, BytesCodec::new()), None));
}
.await??;
stream.set_nodelay(true).ok();
let addr = stream.local_addr()?;
return Ok(Self(
Framed::new(DynTcpStream(Box::new(stream)), BytesCodec::new()),
addr,
None,
0,
));
}
}
bail!("could not resolve to any address");
}
pub fn from(stream: TcpStream) -> Self {
Self(Framed::new(stream, BytesCodec::new()), None)
pub async fn connect<'a, 't, P, T1, T2>(
proxy: P,
target: T1,
local: T2,
username: &'a str,
password: &'a str,
ms_timeout: u64,
) -> ResultType<Self>
where
P: ToProxyAddrs,
T1: IntoTargetAddr<'t>,
T2: ToSocketAddrs,
{
if let Some(local) = lookup_host(&local).await?.next() {
if let Some(proxy) = proxy.to_proxy_addrs().next().await {
let stream =
super::timeout(ms_timeout, new_socket(local, true)?.connect(proxy?)).await??;
stream.set_nodelay(true).ok();
let stream = if username.trim().is_empty() {
super::timeout(
ms_timeout,
Socks5Stream::connect_with_socket(stream, target),
)
.await??
} else {
super::timeout(
ms_timeout,
Socks5Stream::connect_with_password_and_socket(
stream, target, username, password,
),
)
.await??
};
let addr = stream.local_addr()?;
return Ok(Self(
Framed::new(DynTcpStream(Box::new(stream)), BytesCodec::new()),
addr,
None,
0,
));
};
};
bail!("could not resolve to any address");
}
pub fn local_addr(&self) -> SocketAddr {
self.1
}
pub fn set_send_timeout(&mut self, ms: u64) {
self.3 = ms;
}
pub fn from(stream: impl TcpStreamTrait + Send + Sync + 'static, addr: SocketAddr) -> Self {
Self(
Framed::new(DynTcpStream(Box::new(stream)), BytesCodec::new()),
addr,
None,
0,
)
}
pub fn set_raw(&mut self) {
self.0.codec_mut().set_raw();
self.1 = None;
self.2 = None;
}
pub fn is_secured(&self) -> bool {
self.1.is_some()
self.2.is_some()
}
#[inline]
@@ -74,24 +177,29 @@ impl FramedStream {
#[inline]
pub async fn send_raw(&mut self, msg: Vec<u8>) -> ResultType<()> {
let mut msg = msg;
if let Some(key) = self.1.as_mut() {
if let Some(key) = self.2.as_mut() {
key.1 += 1;
let nonce = Self::get_nonce(key.1);
msg = secretbox::seal(&msg, &nonce, &key.0);
}
self.0.send(bytes::Bytes::from(msg)).await?;
self.send_bytes(bytes::Bytes::from(msg)).await?;
Ok(())
}
#[inline]
pub async fn send_bytes(&mut self, bytes: Bytes) -> ResultType<()> {
self.0.send(bytes).await?;
if self.3 > 0 {
super::timeout(self.3, self.0.send(bytes)).await??;
} else {
self.0.send(bytes).await?;
}
Ok(())
}
#[inline]
pub async fn next(&mut self) -> Option<Result<BytesMut, Error>> {
let mut res = self.0.next().await;
if let Some(key) = self.1.as_mut() {
if let Some(key) = self.2.as_mut() {
if let Some(Ok(bytes)) = res.as_mut() {
key.2 += 1;
let nonce = Self::get_nonce(key.2);
@@ -119,28 +227,59 @@ impl FramedStream {
}
pub fn set_key(&mut self, key: Key) {
self.1 = Some((key, 0, 0));
self.2 = Some((key, 0, 0));
}
fn get_nonce(seqnum: u64) -> Nonce {
let mut nonce = Nonce([0u8; secretbox::NONCEBYTES]);
nonce.0[..std::mem::size_of_val(&seqnum)].copy_from_slice(&seqnum.to_ne_bytes());
nonce.0[..std::mem::size_of_val(&seqnum)].copy_from_slice(&seqnum.to_le_bytes());
nonce
}
}
const DEFAULT_BACKLOG: i32 = 128;
const DEFAULT_BACKLOG: u32 = 128;
#[allow(clippy::never_loop)]
pub async fn new_listener<T: ToSocketAddrs>(addr: T, reuse: bool) -> ResultType<TcpListener> {
if !reuse {
Ok(TcpListener::bind(addr).await?)
} else {
for addr in addr.to_socket_addrs().await? {
let socket = super::new_socket(addr, true, true)?;
socket.listen(DEFAULT_BACKLOG)?;
return Ok(TcpListener::from_std(socket.into_tcp_listener())?);
for addr in lookup_host(&addr).await? {
let socket = new_socket(addr, true)?;
return Ok(socket.listen(DEFAULT_BACKLOG)?);
}
bail!("could not resolve to any address");
}
}
impl Unpin for DynTcpStream {}
impl AsyncRead for DynTcpStream {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
AsyncRead::poll_read(Pin::new(&mut self.0), cx, buf)
}
}
impl AsyncWrite for DynTcpStream {
fn poll_write(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
AsyncWrite::poll_write(Pin::new(&mut self.0), cx, buf)
}
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
AsyncWrite::poll_flush(Pin::new(&mut self.0), cx)
}
fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
AsyncWrite::poll_shutdown(Pin::new(&mut self.0), cx)
}
}
impl<R: AsyncRead + AsyncWrite + Unpin> TcpStreamTrait for R {}

View File

@@ -1,71 +1,140 @@
use crate::{bail, ResultType};
use bytes::BytesMut;
use futures::SinkExt;
use anyhow::anyhow;
use bytes::{Bytes, BytesMut};
use futures::{SinkExt, StreamExt};
use protobuf::Message;
use std::{
io::Error,
net::SocketAddr,
ops::{Deref, DerefMut},
};
use tokio::{net::ToSocketAddrs, net::UdpSocket, stream::StreamExt};
use socket2::{Domain, Socket, Type};
use std::net::SocketAddr;
use tokio::net::{ToSocketAddrs, UdpSocket};
use tokio_socks::{udp::Socks5UdpFramed, IntoTargetAddr, TargetAddr, ToProxyAddrs};
use tokio_util::{codec::BytesCodec, udp::UdpFramed};
pub struct FramedSocket(UdpFramed<BytesCodec>);
impl Deref for FramedSocket {
type Target = UdpFramed<BytesCodec>;
fn deref(&self) -> &Self::Target {
&self.0
}
pub enum FramedSocket {
Direct(UdpFramed<BytesCodec>),
ProxySocks(Socks5UdpFramed),
}
impl DerefMut for FramedSocket {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
fn new_socket(addr: SocketAddr, reuse: bool) -> Result<Socket, std::io::Error> {
let socket = match addr {
SocketAddr::V4(..) => Socket::new(Domain::ipv4(), Type::dgram(), None),
SocketAddr::V6(..) => Socket::new(Domain::ipv6(), Type::dgram(), None),
}?;
if reuse {
// windows has no reuse_port, but it's reuse_address
// almost equals to unix's reuse_port + reuse_address,
// though may introduce nondeterministic behavior
#[cfg(unix)]
socket.set_reuse_port(true)?;
socket.set_reuse_address(true)?;
}
socket.bind(&addr.into())?;
Ok(socket)
}
impl FramedSocket {
pub async fn new<T: ToSocketAddrs>(addr: T) -> ResultType<Self> {
let socket = UdpSocket::bind(addr).await?;
Ok(Self(UdpFramed::new(socket, BytesCodec::new())))
Ok(Self::Direct(UdpFramed::new(socket, BytesCodec::new())))
}
#[allow(clippy::never_loop)]
pub async fn new_reuse<T: ToSocketAddrs>(addr: T) -> ResultType<Self> {
for addr in addr.to_socket_addrs().await? {
return Ok(Self(UdpFramed::new(
UdpSocket::from_std(super::new_socket(addr, false, true)?.into_udp_socket())?,
pub async fn new_reuse<T: std::net::ToSocketAddrs>(addr: T) -> ResultType<Self> {
for addr in addr.to_socket_addrs()? {
let socket = new_socket(addr, true)?.into_udp_socket();
return Ok(Self::Direct(UdpFramed::new(
UdpSocket::from_std(socket)?,
BytesCodec::new(),
)));
}
bail!("could not resolve to any address");
}
pub async fn new_proxy<'a, 't, P: ToProxyAddrs, T: ToSocketAddrs>(
proxy: P,
local: T,
username: &'a str,
password: &'a str,
ms_timeout: u64,
) -> ResultType<Self> {
let framed = if username.trim().is_empty() {
super::timeout(ms_timeout, Socks5UdpFramed::connect(proxy, Some(local))).await??
} else {
super::timeout(
ms_timeout,
Socks5UdpFramed::connect_with_password(proxy, Some(local), username, password),
)
.await??
};
log::trace!(
"Socks5 udp connected, local addr: {:?}, target addr: {}",
framed.local_addr(),
framed.socks_addr()
);
Ok(Self::ProxySocks(framed))
}
#[inline]
pub async fn send(&mut self, msg: &impl Message, addr: SocketAddr) -> ResultType<()> {
self.0
.send((bytes::Bytes::from(msg.write_to_bytes().unwrap()), addr))
.await?;
pub async fn send(
&mut self,
msg: &impl Message,
addr: impl IntoTargetAddr<'_>,
) -> ResultType<()> {
let addr = addr.into_target_addr()?.to_owned();
let send_data = Bytes::from(msg.write_to_bytes()?);
let _ = match self {
Self::Direct(f) => match addr {
TargetAddr::Ip(addr) => f.send((send_data, addr)).await?,
_ => {}
},
Self::ProxySocks(f) => f.send((send_data, addr)).await?,
};
Ok(())
}
// https://stackoverflow.com/a/68733302/1926020
#[inline]
pub async fn send_raw(
&mut self,
msg: &'static [u8],
addr: impl IntoTargetAddr<'static>,
) -> ResultType<()> {
let addr = addr.into_target_addr()?.to_owned();
let _ = match self {
Self::Direct(f) => match addr {
TargetAddr::Ip(addr) => f.send((Bytes::from(msg), addr)).await?,
_ => {}
},
Self::ProxySocks(f) => f.send((Bytes::from(msg), addr)).await?,
};
Ok(())
}
#[inline]
pub async fn send_raw(&mut self, msg: &'static [u8], addr: SocketAddr) -> ResultType<()> {
self.0.send((bytes::Bytes::from(msg), addr)).await?;
Ok(())
pub async fn next(&mut self) -> Option<ResultType<(BytesMut, TargetAddr<'static>)>> {
match self {
Self::Direct(f) => match f.next().await {
Some(Ok((data, addr))) => {
Some(Ok((data, addr.into_target_addr().ok()?.to_owned())))
}
Some(Err(e)) => Some(Err(anyhow!(e))),
None => None,
},
Self::ProxySocks(f) => match f.next().await {
Some(Ok((data, _))) => Some(Ok((data.data, data.dst_addr))),
Some(Err(e)) => Some(Err(anyhow!(e))),
None => None,
},
}
}
#[inline]
pub async fn next(&mut self) -> Option<Result<(BytesMut, SocketAddr), Error>> {
self.0.next().await
}
#[inline]
pub async fn next_timeout(&mut self, ms: u64) -> Option<Result<(BytesMut, SocketAddr), Error>> {
pub async fn next_timeout(
&mut self,
ms: u64,
) -> Option<ResultType<(BytesMut, TargetAddr<'static>)>> {
if let Ok(res) =
tokio::time::timeout(std::time::Duration::from_millis(ms), self.0.next()).await
tokio::time::timeout(std::time::Duration::from_millis(ms), self.next()).await
{
res
} else {

View File

@@ -1,2 +0,0 @@
target
Cargo.lock

View File

@@ -1,18 +0,0 @@
[package]
name = "magnum-opus"
version = "0.3.4"
authors = ["Tad Hardesty <tad@platymuus.com>", "Sergey Duck <sergeypechnikov326@gmail.com>"]
edition = "2018"
description = "Safe Rust bindings for libopus"
readme = "README.md"
license = "MIT/Apache-2.0"
keywords = ["opus", "codec", "voice", "sound", "audio"]
categories = ["api-bindings", "encoding", "compression",
"multimedia::audio", "multimedia::encoding"]
repository = "https://github.com/DuckerMan/magnum-opus"
documentation = "https://docs.rs/magnum-opus"
[build-dependencies]
target_build_utils = "0.3"
bindgen = "0.53"

View File

@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,19 +0,0 @@
Copyright (c) 2016 Tad Hardesty
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,22 +0,0 @@
# magnum-opus [![](https://meritbadge.herokuapp.com/magnum-opus)](https://crates.io/crates/magnum-opus) [![](https://img.shields.io/badge/docs-online-2020ff.svg)](https://docs.rs/magnum-opus)
### This is the fork of @SpaceManiac repo, which now is abandoned
Safe Rust bindings for libopus. The rustdoc (available through `cargo doc`)
includes brief descriptions for methods, and detailed API information can be
found at the [libopus documentation](https://opus-codec.org/docs/opus_api-1.1.2/).
## License
Licensed under either of
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

View File

@@ -1,89 +0,0 @@
use std::{
env,
path::{Path, PathBuf},
};
fn find_package(name: &str) -> Vec<PathBuf> {
let vcpkg_root = std::env::var("VCPKG_ROOT").unwrap();
let mut path: PathBuf = vcpkg_root.into();
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
let mut target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
if target_arch == "x86_64" {
target_arch = "x64".to_owned();
} else if target_arch == "aarch64" {
target_arch = "arm64".to_owned();
} else {
target_arch = "arm".to_owned();
}
let target = if target_os == "macos" {
"x64-osx".to_owned()
} else if target_os == "windows" {
"x64-windows-static".to_owned()
} else if target_os == "android" {
format!("{}-android-static", target_arch)
} else {
"x64-linux".to_owned()
};
println!("cargo:info={}", target);
path.push("installed");
path.push(target);
println!(
"{}",
format!("cargo:rustc-link-lib={}", name.trim_start_matches("lib"))
);
println!(
"{}",
format!(
"cargo:rustc-link-search={}",
path.join("lib").to_str().unwrap()
)
);
let include = path.join("include");
println!("{}", format!("cargo:include={}", include.to_str().unwrap()));
vec![include]
}
fn generate_bindings(ffi_header: &Path, include_paths: &[PathBuf], ffi_rs: &Path) {
#[derive(Debug)]
struct ParseCallbacks;
impl bindgen::callbacks::ParseCallbacks for ParseCallbacks {
fn int_macro(&self, name: &str, _value: i64) -> Option<bindgen::callbacks::IntKind> {
if name.starts_with("OPUS") {
Some(bindgen::callbacks::IntKind::Int)
} else {
None
}
}
}
let mut b = bindgen::Builder::default()
.header(ffi_header.to_str().unwrap())
.parse_callbacks(Box::new(ParseCallbacks))
.generate_comments(false);
for dir in include_paths {
b = b.clang_arg(format!("-I{}", dir.display()));
}
b.generate().unwrap().write_to_file(ffi_rs).unwrap();
}
fn gen_opus() {
let includes = find_package("opus");
let src_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
let src_dir = Path::new(&src_dir);
let out_dir = env::var_os("OUT_DIR").unwrap();
let out_dir = Path::new(&out_dir);
let ffi_header = src_dir.join("opus_ffi.h");
println!("rerun-if-changed={}", ffi_header.display());
for dir in &includes {
println!("rerun-if-changed={}", dir.display());
}
let ffi_rs = out_dir.join("opus_ffi.rs");
generate_bindings(&ffi_header, &includes, &ffi_rs);
}
fn main() {
gen_opus()
}

View File

@@ -1 +0,0 @@
#include <opus/opus_multistream.h>

View File

@@ -1,843 +0,0 @@
// Copyright 2016 Tad Hardesty
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! High-level bindings for libopus.
//!
//! Only brief descriptions are included here. For detailed information, consult
//! the [libopus documentation](https://opus-codec.org/docs/opus_api-1.1.2/).
#![warn(missing_docs)]
mod opus_ffi;
use opus_ffi as ffi;
use std::ffi::CStr;
use std::marker::PhantomData;
use std::os::raw::c_int;
// ============================================================================
// Constants
// Generic CTLs
const OPUS_RESET_STATE: c_int = 4028; // void
const OPUS_GET_FINAL_RANGE: c_int = 4031; // out *u32
const OPUS_GET_BANDWIDTH: c_int = 4009; // out *i32
const OPUS_GET_SAMPLE_RATE: c_int = 4029; // out *i32
// Encoder CTLs
const OPUS_SET_BITRATE: c_int = 4002; // in i32
const OPUS_GET_BITRATE: c_int = 4003; // out *i32
const OPUS_SET_VBR: c_int = 4006; // in i32
const OPUS_GET_VBR: c_int = 4007; // out *i32
const OPUS_SET_VBR_CONSTRAINT: c_int = 4020; // in i32
const OPUS_GET_VBR_CONSTRAINT: c_int = 4021; // out *i32
const OPUS_SET_INBAND_FEC: c_int = 4012; // in i32
const OPUS_GET_INBAND_FEC: c_int = 4013; // out *i32
const OPUS_SET_PACKET_LOSS_PERC: c_int = 4014; // in i32
const OPUS_GET_PACKET_LOSS_PERC: c_int = 4015; // out *i32
const OPUS_GET_LOOKAHEAD: c_int = 4027; // out *i32
// Decoder CTLs
const OPUS_SET_GAIN: c_int = 4034; // in i32
const OPUS_GET_GAIN: c_int = 4045; // out *i32
const OPUS_GET_LAST_PACKET_DURATION: c_int = 4039; // out *i32
const OPUS_GET_PITCH: c_int = 4033; // out *i32
// Bitrate
const OPUS_AUTO: c_int = -1000;
const OPUS_BITRATE_MAX: c_int = -1;
/// The possible applications for the codec.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum Application {
/// Best for most VoIP/videoconference applications where listening quality
/// and intelligibility matter most.
Voip = 2048,
/// Best for broadcast/high-fidelity application where the decoded audio
/// should be as close as possible to the input.
Audio = 2049,
/// Only use when lowest-achievable latency is what matters most.
LowDelay = 2051,
}
/// The available channel setings.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum Channels {
/// One channel.
Mono = 1,
/// Two channels, left and right.
Stereo = 2,
}
/// The available bandwidth level settings.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum Bandwidth {
/// Auto/default setting.
Auto = -1000,
/// 4kHz bandpass.
Narrowband = 1101,
/// 6kHz bandpass.
Mediumband = 1102,
/// 8kHz bandpass.
Wideband = 1103,
/// 12kHz bandpass.
Superwideband = 1104,
/// 20kHz bandpass.
Fullband = 1105,
}
impl Bandwidth {
fn from_int(value: i32) -> Option<Bandwidth> {
Some(match value {
-1000 => Bandwidth::Auto,
1101 => Bandwidth::Narrowband,
1102 => Bandwidth::Mediumband,
1103 => Bandwidth::Wideband,
1104 => Bandwidth::Superwideband,
1105 => Bandwidth::Fullband,
_ => return None,
})
}
fn decode(value: i32, what: &'static str) -> Result<Bandwidth> {
match Bandwidth::from_int(value) {
Some(bandwidth) => Ok(bandwidth),
None => Err(Error::bad_arg(what)),
}
}
}
/// Possible error codes.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum ErrorCode {
/// One or more invalid/out of range arguments.
BadArg = -1,
/// Not enough bytes allocated in the buffer.
BufferTooSmall = -2,
/// An internal error was detected.
InternalError = -3,
/// The compressed data passed is corrupted.
InvalidPacket = -4,
/// Invalid/unsupported request number.
Unimplemented = -5,
/// An encoder or decoder structure is invalid or already freed.
InvalidState = -6,
/// Memory allocation has failed.
AllocFail = -7,
/// An unknown failure.
Unknown = -8,
}
impl ErrorCode {
fn from_int(value: c_int) -> ErrorCode {
use ErrorCode::*;
match value {
ffi::OPUS_BAD_ARG => BadArg,
ffi::OPUS_BUFFER_TOO_SMALL => BufferTooSmall,
ffi::OPUS_INTERNAL_ERROR => InternalError,
ffi::OPUS_INVALID_PACKET => InvalidPacket,
ffi::OPUS_UNIMPLEMENTED => Unimplemented,
ffi::OPUS_INVALID_STATE => InvalidState,
ffi::OPUS_ALLOC_FAIL => AllocFail,
_ => Unknown,
}
}
/// Get a human-readable error string for this error code.
pub fn description(self) -> &'static str {
// should always be ASCII and non-null for any input
unsafe { CStr::from_ptr(ffi::opus_strerror(self as c_int)) }.to_str().unwrap()
}
}
/// Possible bitrates.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Bitrate {
/// Explicit bitrate choice (in bits/second).
Bits(i32),
/// Maximum bitrate allowed (up to maximum number of bytes for the packet).
Max,
/// Default bitrate decided by the encoder (not recommended).
Auto,
}
/// Get the libopus version string.
///
/// Applications may look for the substring "-fixed" in the version string to
/// determine whether they have a fixed-point or floating-point build at
/// runtime.
pub fn version() -> &'static str {
// verison string should always be ASCII
unsafe { CStr::from_ptr(ffi::opus_get_version_string()) }.to_str().unwrap()
}
macro_rules! ffi {
($f:ident $(, $rest:expr)*) => {
match unsafe { ffi::$f($($rest),*) } {
code if code < 0 => return Err(Error::from_code(stringify!($f), code)),
code => code,
}
}
}
macro_rules! ctl {
($f:ident, $this:ident, $ctl:ident, $($rest:expr),*) => {
match unsafe { ffi::$f($this.ptr, $ctl, $($rest),*) } {
code if code < 0 => return Err(Error::from_code(
concat!(stringify!($f), "(", stringify!($ctl), ")"),
code,
)),
_ => (),
}
}
}
// ============================================================================
// Encoder
macro_rules! enc_ctl {
($this:ident, $ctl:ident $(, $rest:expr)*) => {
ctl!(opus_encoder_ctl, $this, $ctl, $($rest),*)
}
}
/// An Opus encoder with associated state.
#[derive(Debug)]
pub struct Encoder {
ptr: *mut ffi::OpusEncoder,
channels: Channels,
}
impl Encoder {
/// Create and initialize an encoder.
pub fn new(sample_rate: u32, channels: Channels, mode: Application) -> Result<Encoder> {
let mut error = 0;
let ptr = unsafe { ffi::opus_encoder_create(
sample_rate as i32,
channels as c_int,
mode as c_int,
&mut error) };
if error != ffi::OPUS_OK || ptr.is_null() {
Err(Error::from_code("opus_encoder_create", error))
} else {
Ok(Encoder { ptr: ptr, channels: channels })
}
}
/// Encode an Opus frame.
pub fn encode(&mut self, input: &[i16], output: &mut [u8]) -> Result<usize> {
let len = ffi!(opus_encode, self.ptr,
input.as_ptr(), len(input) / self.channels as c_int,
output.as_mut_ptr(), len(output));
Ok(len as usize)
}
/// Encode an Opus frame from floating point input.
pub fn encode_float(&mut self, input: &[f32], output: &mut [u8]) -> Result<usize> {
let len = ffi!(opus_encode_float, self.ptr,
input.as_ptr(), len(input) / self.channels as c_int,
output.as_mut_ptr(), len(output));
Ok(len as usize)
}
/// Encode an Opus frame to a new buffer.
pub fn encode_vec(&mut self, input: &[i16], max_size: usize) -> Result<Vec<u8>> {
let mut output: Vec<u8> = vec![0; max_size];
let result = self.encode(input, output.as_mut_slice())?;
output.truncate(result);
Ok(output)
}
/// Encode an Opus frame from floating point input to a new buffer.
pub fn encode_vec_float(&mut self, input: &[f32], max_size: usize) -> Result<Vec<u8>> {
let mut output: Vec<u8> = vec![0; max_size];
let result = self.encode_float(input, output.as_mut_slice())?;
output.truncate(result);
Ok(output)
}
// ------------
// Generic CTLs
/// Reset the codec state to be equivalent to a freshly initialized state.
pub fn reset_state(&mut self) -> Result<()> {
enc_ctl!(self, OPUS_RESET_STATE);
Ok(())
}
/// Get the final range of the codec's entropy coder.
pub fn get_final_range(&mut self) -> Result<u32> {
let mut value: u32 = 0;
enc_ctl!(self, OPUS_GET_FINAL_RANGE, &mut value);
Ok(value)
}
/// Get the encoder's configured bandpass.
pub fn get_bandwidth(&mut self) -> Result<Bandwidth> {
let mut value: i32 = 0;
enc_ctl!(self, OPUS_GET_BANDWIDTH, &mut value);
Bandwidth::decode(value, "opus_encoder_ctl(OPUS_GET_BANDWIDTH)")
}
/// Get the samping rate the encoder was intialized with.
pub fn get_sample_rate(&mut self) -> Result<u32> {
let mut value: i32 = 0;
enc_ctl!(self, OPUS_GET_SAMPLE_RATE, &mut value);
Ok(value as u32)
}
// ------------
// Encoder CTLs
/// Set the encoder's bitrate.
pub fn set_bitrate(&mut self, value: Bitrate) -> Result<()> {
let value: i32 = match value {
Bitrate::Auto => OPUS_AUTO,
Bitrate::Max => OPUS_BITRATE_MAX,
Bitrate::Bits(b) => b,
};
enc_ctl!(self, OPUS_SET_BITRATE, value);
Ok(())
}
/// Get the encoder's bitrate.
pub fn get_bitrate(&mut self) -> Result<Bitrate> {
let mut value: i32 = 0;
enc_ctl!(self, OPUS_GET_BITRATE, &mut value);
Ok(match value {
OPUS_AUTO => Bitrate::Auto,
OPUS_BITRATE_MAX => Bitrate::Max,
_ => Bitrate::Bits(value),
})
}
/// Enable or disable variable bitrate.
pub fn set_vbr(&mut self, vbr: bool) -> Result<()> {
let value: i32 = if vbr { 1 } else { 0 };
enc_ctl!(self, OPUS_SET_VBR, value);
Ok(())
}
/// Determine if variable bitrate is enabled.
pub fn get_vbr(&mut self) -> Result<bool> {
let mut value: i32 = 0;
enc_ctl!(self, OPUS_GET_VBR, &mut value);
Ok(value != 0)
}
/// Enable or disable constrained VBR.
pub fn set_vbr_constraint(&mut self, vbr: bool) -> Result<()> {
let value: i32 = if vbr { 1 } else { 0 };
enc_ctl!(self, OPUS_SET_VBR_CONSTRAINT, value);
Ok(())
}
/// Determine if constrained VBR is enabled.
pub fn get_vbr_constraint(&mut self) -> Result<bool> {
let mut value: i32 = 0;
enc_ctl!(self, OPUS_GET_VBR_CONSTRAINT, &mut value);
Ok(value != 0)
}
/// Configures the encoder's use of inband forward error correction (FEC).
pub fn set_inband_fec(&mut self, value: bool) -> Result<()> {
let value: i32 = if value { 1 } else { 0 };
enc_ctl!(self, OPUS_SET_INBAND_FEC, value);
Ok(())
}
/// Gets encoder's configured use of inband forward error correction.
pub fn get_inband_fec(&mut self) -> Result<bool> {
let mut value: i32 = 0;
enc_ctl!(self, OPUS_GET_INBAND_FEC, &mut value);
Ok(value != 0)
}
/// Sets the encoder's expected packet loss percentage.
pub fn set_packet_loss_perc(&mut self, value: i32) -> Result<()> {
enc_ctl!(self, OPUS_SET_PACKET_LOSS_PERC, value);
Ok(())
}
/// Gets the encoder's expected packet loss percentage.
pub fn get_packet_loss_perc(&mut self) -> Result<i32> {
let mut value: i32 = 0;
enc_ctl!(self, OPUS_GET_PACKET_LOSS_PERC, &mut value);
Ok(value)
}
/// Gets the total samples of delay added by the entire codec.
pub fn get_lookahead(&mut self) -> Result<i32> {
let mut value: i32 = 0;
enc_ctl!(self, OPUS_GET_LOOKAHEAD, &mut value);
Ok(value)
}
// TODO: Encoder-specific CTLs
}
impl Drop for Encoder {
fn drop(&mut self) {
unsafe { ffi::opus_encoder_destroy(self.ptr) }
}
}
// "A single codec state may only be accessed from a single thread at
// a time and any required locking must be performed by the caller. Separate
// streams must be decoded with separate decoder states and can be decoded
// in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK
// defined."
//
// In other words, opus states may be moved between threads at will. A special
// compilation mode intended for embedded platforms forbids multithreaded use
// of the library as a whole rather than on a per-state basis, but the opus-sys
// crate does not use this mode.
unsafe impl Send for Encoder {}
// ============================================================================
// Decoder
macro_rules! dec_ctl {
($this:ident, $ctl:ident $(, $rest:expr)*) => {
ctl!(opus_decoder_ctl, $this, $ctl, $($rest),*)
}
}
/// An Opus decoder with associated state.
#[derive(Debug)]
pub struct Decoder {
ptr: *mut ffi::OpusDecoder,
channels: Channels,
}
impl Decoder {
/// Create and initialize a decoder.
pub fn new(sample_rate: u32, channels: Channels) -> Result<Decoder> {
let mut error = 0;
let ptr = unsafe { ffi::opus_decoder_create(
sample_rate as i32,
channels as c_int,
&mut error) };
if error != ffi::OPUS_OK || ptr.is_null() {
Err(Error::from_code("opus_decoder_create", error))
} else {
Ok(Decoder { ptr: ptr, channels: channels })
}
}
/// Decode an Opus packet.
pub fn decode(&mut self, input: &[u8], output: &mut [i16], fec: bool) -> Result<usize> {
let ptr = match input.len() {
0 => std::ptr::null(),
_ => input.as_ptr(),
};
let len = ffi!(opus_decode, self.ptr,
ptr, len(input),
output.as_mut_ptr(), len(output) / self.channels as c_int,
fec as c_int);
Ok(len as usize)
}
/// Decode an Opus packet with floating point output.
pub fn decode_float(&mut self, input: &[u8], output: &mut [f32], fec: bool) -> Result<usize> {
let ptr = match input.len() {
0 => std::ptr::null(),
_ => input.as_ptr(),
};
let len = ffi!(opus_decode_float, self.ptr,
ptr, len(input),
output.as_mut_ptr(), len(output) / self.channels as c_int,
fec as c_int);
Ok(len as usize)
}
/// Get the number of samples of an Opus packet.
pub fn get_nb_samples(&self, packet: &[u8]) -> Result<usize> {
let len = ffi!(opus_decoder_get_nb_samples, self.ptr,
packet.as_ptr(), packet.len() as i32);
Ok(len as usize)
}
// ------------
// Generic CTLs
/// Reset the codec state to be equivalent to a freshly initialized state.
pub fn reset_state(&mut self) -> Result<()> {
dec_ctl!(self, OPUS_RESET_STATE);
Ok(())
}
/// Get the final range of the codec's entropy coder.
pub fn get_final_range(&mut self) -> Result<u32> {
let mut value: u32 = 0;
dec_ctl!(self, OPUS_GET_FINAL_RANGE, &mut value);
Ok(value)
}
/// Get the decoder's last bandpass.
pub fn get_bandwidth(&mut self) -> Result<Bandwidth> {
let mut value: i32 = 0;
dec_ctl!(self, OPUS_GET_BANDWIDTH, &mut value);
Bandwidth::decode(value, "opus_decoder_ctl(OPUS_GET_BANDWIDTH)")
}
/// Get the samping rate the decoder was intialized with.
pub fn get_sample_rate(&mut self) -> Result<u32> {
let mut value: i32 = 0;
dec_ctl!(self, OPUS_GET_SAMPLE_RATE, &mut value);
Ok(value as u32)
}
// ------------
// Decoder CTLs
/// Configures decoder gain adjustment.
///
/// Scales the decoded output by a factor specified in Q8 dB units. This has
/// a maximum range of -32768 to 32768 inclusive, and returns `BadArg`
/// otherwise. The default is zero indicating no adjustment. This setting
/// survives decoder reset.
///
/// `gain = pow(10, x / (20.0 * 256))`
pub fn set_gain(&mut self, gain: i32) -> Result<()> {
dec_ctl!(self, OPUS_SET_GAIN, gain);
Ok(())
}
/// Gets the decoder's configured gain adjustment.
pub fn get_gain(&mut self) -> Result<i32> {
let mut value: i32 = 0;
dec_ctl!(self, OPUS_GET_GAIN, &mut value);
Ok(value)
}
/// Gets the duration (in samples) of the last packet successfully decoded
/// or concealed.
pub fn get_last_packet_duration(&mut self) -> Result<u32> {
let mut value: i32 = 0;
dec_ctl!(self, OPUS_GET_LAST_PACKET_DURATION, &mut value);
Ok(value as u32)
}
/// Gets the pitch of the last decoded frame, if available.
///
/// This can be used for any post-processing algorithm requiring the use of
/// pitch, e.g. time stretching/shortening. If the last frame was not
/// voiced, or if the pitch was not coded in the frame, then zero is
/// returned.
pub fn get_pitch(&mut self) -> Result<i32> {
let mut value: i32 = 0;
dec_ctl!(self, OPUS_GET_PITCH, &mut value);
Ok(value)
}
}
impl Drop for Decoder {
fn drop(&mut self) {
unsafe { ffi::opus_decoder_destroy(self.ptr) }
}
}
// See `unsafe impl Send for Encoder`.
unsafe impl Send for Decoder {}
// ============================================================================
// Packet Analysis
/// Analyze raw Opus packets.
pub mod packet {
use super::*;
use super::ffi;
use std::{ptr, slice};
/// Get the bandwidth of an Opus packet.
pub fn get_bandwidth(packet: &[u8]) -> Result<Bandwidth> {
if packet.len() < 1 {
return Err(Error::bad_arg("opus_packet_get_bandwidth"));
}
let bandwidth = ffi!(opus_packet_get_bandwidth, packet.as_ptr());
Bandwidth::decode(bandwidth, "opus_packet_get_bandwidth")
}
/// Get the number of channels from an Opus packet.
pub fn get_nb_channels(packet: &[u8]) -> Result<Channels> {
if packet.len() < 1 {
return Err(Error::bad_arg("opus_packet_get_nb_channels"));
}
let channels = ffi!(opus_packet_get_nb_channels, packet.as_ptr());
match channels {
1 => Ok(Channels::Mono),
2 => Ok(Channels::Stereo),
_ => Err(Error::bad_arg("opus_packet_get_nb_channels")),
}
}
/// Get the number of frames in an Opus packet.
pub fn get_nb_frames(packet: &[u8]) -> Result<usize> {
let frames = ffi!(opus_packet_get_nb_frames, packet.as_ptr(), len(packet));
Ok(frames as usize)
}
/// Get the number of samples of an Opus packet.
pub fn get_nb_samples(packet: &[u8], sample_rate: u32) -> Result<usize> {
let frames = ffi!(opus_packet_get_nb_samples,
packet.as_ptr(), len(packet),
sample_rate as c_int);
Ok(frames as usize)
}
/// Get the number of samples per frame from an Opus packet.
pub fn get_samples_per_frame(packet: &[u8], sample_rate: u32) -> Result<usize> {
if packet.len() < 1 {
return Err(Error::bad_arg("opus_packet_get_samples_per_frame"))
}
let samples = ffi!(opus_packet_get_samples_per_frame,
packet.as_ptr(), sample_rate as c_int);
Ok(samples as usize)
}
/// Parse an Opus packet into one or more frames.
pub fn parse(packet: &[u8]) -> Result<Packet> {
let mut toc: u8 = 0;
let mut frames = [ptr::null(); 48];
let mut sizes = [0i16; 48];
let mut payload_offset: i32 = 0;
let num_frames = ffi!(opus_packet_parse,
packet.as_ptr(), len(packet),
&mut toc, frames.as_mut_ptr(),
sizes.as_mut_ptr(), &mut payload_offset);
let mut frames_vec = Vec::with_capacity(num_frames as usize);
for i in 0..num_frames as usize {
frames_vec.push(unsafe { slice::from_raw_parts(frames[i], sizes[i] as usize) });
}
Ok(Packet {
toc: toc,
frames: frames_vec,
payload_offset: payload_offset as usize,
})
}
/// A parsed Opus packet, retuned from `parse`.
#[derive(Debug)]
pub struct Packet<'a> {
/// The TOC byte of the packet.
pub toc: u8,
/// The frames contained in the packet.
pub frames: Vec<&'a [u8]>,
/// The offset into the packet at which the payload is located.
pub payload_offset: usize,
}
/// Pad a given Opus packet to a larger size.
///
/// The packet will be extended from the first `prev_len` bytes of the
/// buffer into the rest of the available space.
pub fn pad(packet: &mut [u8], prev_len: usize) -> Result<usize> {
let result = ffi!(opus_packet_pad, packet.as_mut_ptr(),
check_len(prev_len), len(packet));
Ok(result as usize)
}
/// Remove all padding from a given Opus packet and rewrite the TOC sequence
/// to minimize space usage.
pub fn unpad(packet: &mut [u8]) -> Result<usize> {
let result = ffi!(opus_packet_unpad, packet.as_mut_ptr(), len(packet));
Ok(result as usize)
}
}
// ============================================================================
// Float Soft Clipping
/// Soft-clipping to bring a float signal within the [-1,1] range.
#[derive(Debug)]
pub struct SoftClip {
channels: Channels,
memory: [f32; 2],
}
impl SoftClip {
/// Initialize a new soft-clipping state.
pub fn new(channels: Channels) -> SoftClip {
SoftClip { channels: channels, memory: [0.0; 2] }
}
/// Apply soft-clipping to a float signal.
pub fn apply(&mut self, signal: &mut [f32]) {
unsafe { ffi::opus_pcm_soft_clip(
signal.as_mut_ptr(),
len(signal) / self.channels as c_int,
self.channels as c_int,
self.memory.as_mut_ptr()) };
}
}
// ============================================================================
// Repacketizer
/// A repacketizer used to merge together or split apart multiple Opus packets.
#[derive(Debug)]
pub struct Repacketizer {
ptr: *mut ffi::OpusRepacketizer,
}
impl Repacketizer {
/// Create and initialize a repacketizer.
pub fn new() -> Result<Repacketizer> {
let ptr = unsafe { ffi::opus_repacketizer_create() };
if ptr.is_null() {
Err(Error::from_code("opus_repacketizer_create", ffi::OPUS_ALLOC_FAIL))
} else {
Ok(Repacketizer { ptr: ptr })
}
}
/// Shortcut to combine several smaller packets into one larger one.
pub fn combine(&mut self, input: &[&[u8]], output: &mut [u8]) -> Result<usize> {
let mut state = self.begin();
for &packet in input {
state.cat(packet)?;
}
state.out(output)
}
/// Begin using the repacketizer.
pub fn begin<'rp, 'buf>(&'rp mut self) -> RepacketizerState<'rp, 'buf> {
unsafe { ffi::opus_repacketizer_init(self.ptr); }
RepacketizerState { rp: self, phantom: PhantomData }
}
}
impl Drop for Repacketizer {
fn drop(&mut self) {
unsafe { ffi::opus_repacketizer_destroy(self.ptr) }
}
}
// See `unsafe impl Send for Encoder`.
unsafe impl Send for Repacketizer {}
// To understand why these lifetime bounds are needed, imagine that the
// repacketizer keeps an internal Vec<&'buf [u8]>, which is added to by cat()
// and accessed by get_nb_frames(), out(), and out_range(). To prove that these
// lifetime bounds are correct, a dummy implementation with the same signatures
// but a real Vec<&'buf [u8]> rather than unsafe blocks may be substituted.
/// An in-progress repacketization.
#[derive(Debug)]
pub struct RepacketizerState<'rp, 'buf> {
rp: &'rp mut Repacketizer,
phantom: PhantomData<&'buf [u8]>,
}
impl<'rp, 'buf> RepacketizerState<'rp, 'buf> {
/// Add a packet to the current repacketizer state.
pub fn cat(&mut self, packet: &'buf [u8]) -> Result<()> {
ffi!(opus_repacketizer_cat, self.rp.ptr,
packet.as_ptr(), len(packet));
Ok(())
}
/// Add a packet to the current repacketizer state, moving it.
#[inline]
pub fn cat_move<'b2>(self, packet: &'b2 [u8]) -> Result<RepacketizerState<'rp, 'b2>> where 'buf: 'b2 {
let mut shorter = self;
shorter.cat(packet)?;
Ok(shorter)
}
/// Get the total number of frames contained in packet data submitted so
/// far via `cat`.
pub fn get_nb_frames(&mut self) -> usize {
unsafe { ffi::opus_repacketizer_get_nb_frames(self.rp.ptr) as usize }
}
/// Construct a new packet from data previously submitted via `cat`.
///
/// All previously submitted frames are used.
pub fn out(&mut self, buffer: &mut [u8]) -> Result<usize> {
let result = ffi!(opus_repacketizer_out, self.rp.ptr,
buffer.as_mut_ptr(), len(buffer));
Ok(result as usize)
}
/// Construct a new packet from data previously submitted via `cat`, with
/// a manually specified subrange.
///
/// The `end` index should not exceed the value of `get_nb_frames()`.
pub fn out_range(&mut self, begin: usize, end: usize, buffer: &mut [u8]) -> Result<usize> {
let result = ffi!(opus_repacketizer_out_range, self.rp.ptr,
check_len(begin), check_len(end),
buffer.as_mut_ptr(), len(buffer));
Ok(result as usize)
}
}
// ============================================================================
// TODO: Multistream API
// ============================================================================
// Error Handling
/// Opus error Result alias.
pub type Result<T> = std::result::Result<T, Error>;
/// An error generated by the Opus library.
#[derive(Debug)]
pub struct Error {
function: &'static str,
code: ErrorCode,
}
impl Error {
fn bad_arg(what: &'static str) -> Error {
Error { function: what, code: ErrorCode::BadArg }
}
fn from_code(what: &'static str, code: c_int) -> Error {
Error { function: what, code: ErrorCode::from_int(code) }
}
/// Get the name of the Opus function from which the error originated.
#[inline]
pub fn function(&self) -> &'static str { self.function }
/// Get a textual description of the error provided by Opus.
#[inline]
pub fn description(&self) -> &'static str { self.code.description() }
/// Get the Opus error code of the error.
#[inline]
pub fn code(&self) -> ErrorCode { self.code }
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}: {}", self.function, self.description())
}
}
impl std::error::Error for Error {
fn description(&self) -> &str {
self.code.description()
}
}
fn check_len(val: usize) -> c_int {
let len = val as c_int;
if len as usize != val {
panic!("length out of range: {}", val);
}
len
}
#[inline]
fn len<T>(slice: &[T]) -> c_int {
check_len(slice.len())
}

View File

@@ -1,6 +0,0 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
include!(concat!(env!("OUT_DIR"), "/opus_ffi.rs"));

View File

@@ -1,10 +0,0 @@
extern crate opus;
fn main() {
let mut rp = opus::Repacketizer::new().unwrap();
let mut wip = rp.begin().cat_move(
&[1, 2, 3]
//~^ ERROR borrowed value does not live long enough
).unwrap();
wip.out(&mut []);
}

View File

@@ -1,13 +0,0 @@
//! Test that supplying empty packets does forward error correction.
extern crate magnum_opus;
use magnum_opus::*;
#[test]
fn blah() {
let mut magnum_opus = Decoder::new(48000, Channels::Mono).unwrap();
let mut output = vec![0i16; 5760];
let size = magnum_opus.decode(&[], &mut output[..], true).unwrap();
assert_eq!(size, 5760);
}

View File

@@ -1,29 +0,0 @@
// Based on libmagnum_opus/tests/test_magnum_opus_padding.c
/* Check for overflow in reading the padding length.
* http://lists.xiph.org/pipermail/magnum_opus/2012-November/001834.html
*/
extern crate magnum_opus;
#[test]
fn test_overflow() {
const PACKETSIZE: usize = 16909318;
const CHANNELS: magnum_opus::Channels = magnum_opus::Channels::Stereo;
const FRAMESIZE: usize = 5760;
let mut input = vec![0xff; PACKETSIZE];
let mut output = vec![0i16; FRAMESIZE * 2];
input[0] = 0xff;
input[1] = 0x41;
*input.last_mut().unwrap() = 0x0b;
let mut decoder = magnum_opus::Decoder::new(48000, CHANNELS).unwrap();
let result = decoder.decode(&input[..], &mut output[..], false);
drop(decoder);
drop(input);
drop(output);
assert_eq!(result.unwrap_err().code(), magnum_opus::ErrorCode::InvalidPacket);
}

View File

@@ -1,127 +0,0 @@
extern crate magnum_opus;
fn check_ascii(s: &str) -> &str {
for &b in s.as_bytes() {
assert!(b < 0x80, "Non-ASCII character in string");
assert!(b > 0x00, "NUL in string")
}
std::str::from_utf8(s.as_bytes()).unwrap()
}
#[test]
fn strings_ascii() {
use magnum_opus::ErrorCode::*;
println!("\nVersion: {}", check_ascii(magnum_opus::version()));
let codes = [BadArg, BufferTooSmall, InternalError, InvalidPacket,
Unimplemented, InvalidState, AllocFail, Unknown];
for &code in codes.iter() {
println!("{:?}: {}", code, check_ascii(code.description()));
}
}
// 48000Hz * 1 channel * 20 ms / 1000
const MONO_20MS: usize = 48000 * 1 * 20 / 1000;
#[test]
fn encode_mono() {
let mut encoder = magnum_opus::Encoder::new(48000, magnum_opus::Channels::Mono, magnum_opus::Application::Audio).unwrap();
let mut output = [0; 256];
let len = encoder.encode(&[0_i16; MONO_20MS], &mut output).unwrap();
assert_eq!(&output[..len], &[248, 255, 254]);
let len = encoder.encode(&[0_i16; MONO_20MS], &mut output).unwrap();
assert_eq!(&output[..len], &[248, 255, 254]);
let len = encoder.encode(&[1_i16; MONO_20MS], &mut output).unwrap();
assert!(len > 190 && len < 220);
let len = encoder.encode(&[0_i16; MONO_20MS], &mut output).unwrap();
assert!(len > 170 && len < 190);
let myvec = encoder.encode_vec(&[1_i16; MONO_20MS], output.len()).unwrap();
assert!(myvec.len() > 120 && myvec.len() < 140);
}
#[test]
fn encode_stereo() {
let mut encoder = magnum_opus::Encoder::new(48000, magnum_opus::Channels::Stereo, magnum_opus::Application::Audio).unwrap();
let mut output = [0; 512];
let len = encoder.encode(&[0_i16; 2 * MONO_20MS], &mut output).unwrap();
assert_eq!(&output[..len], &[252, 255, 254]);
let len = encoder.encode(&[0_i16; 4 * MONO_20MS], &mut output).unwrap();
assert_eq!(&output[..len], &[253, 255, 254, 255, 254]);
let len = encoder.encode(&[17_i16; 2 * MONO_20MS], &mut output).unwrap();
assert!(len > 240);
let len = encoder.encode(&[0_i16; 2 * MONO_20MS], &mut output).unwrap();
assert!(len > 240);
// Very small buffer should still succeed
let len = encoder.encode(&[95_i16; 2 * MONO_20MS], &mut [0; 20]).unwrap();
assert!(len <= 20);
let myvec = encoder.encode_vec(&[95_i16; 2 * MONO_20MS], 20).unwrap();
assert!(myvec.len() <= 20);
}
#[test]
fn encode_bad_rate() {
match magnum_opus::Encoder::new(48001, magnum_opus::Channels::Mono, magnum_opus::Application::Audio) {
Ok(_) => panic!("Encoder::new did not return BadArg"),
Err(err) => assert_eq!(err.code(), magnum_opus::ErrorCode::BadArg),
}
}
#[test]
fn encode_bad_buffer() {
let mut encoder = magnum_opus::Encoder::new(48000, magnum_opus::Channels::Stereo, magnum_opus::Application::Audio).unwrap();
match encoder.encode(&[1_i16; 2 * MONO_20MS], &mut [0; 0]) {
Ok(_) => panic!("encode with 0-length buffer did not return BadArg"),
Err(err) => assert_eq!(err.code(), magnum_opus::ErrorCode::BadArg),
}
}
#[test]
fn repacketizer() {
let mut rp = magnum_opus::Repacketizer::new().unwrap();
let mut out = [0; 256];
for _ in 0..2 {
let packet1 = [249, 255, 254, 255, 254];
let packet2 = [248, 255, 254];
let mut state = rp.begin();
state.cat(&packet1).unwrap();
state.cat(&packet2).unwrap();
let len = state.out(&mut out).unwrap();
assert_eq!(&out[..len], &[251, 3, 255, 254, 255, 254, 255, 254]);
}
for _ in 0..2 {
let packet = [248, 255, 254];
let state = rp.begin().cat_move(&packet).unwrap();
let packet = [249, 255, 254, 255, 254];
let state = state.cat_move(&packet).unwrap();
let len = {state}.out(&mut out).unwrap();
assert_eq!(&out[..len], &[251, 3, 255, 254, 255, 254, 255, 254]);
}
for _ in 0..2 {
let len = rp.combine(&[
&[249, 255, 254, 255, 254],
&[248, 255, 254],
], &mut out).unwrap();
assert_eq!(&out[..len], &[251, 3, 255, 254, 255, 254, 255, 254]);
}
for _ in 0..2 {
let len = rp.begin()
.cat_move(&[248, 255, 254]).unwrap()
.cat_move(&[248, 71, 71]).unwrap()
.out(&mut out).unwrap();
assert_eq!(&out[..len], &[249, 255, 254, 71, 71]);
}
}

View File

@@ -1,3 +0,0 @@
target
Cargo.lock
.idea

View File

@@ -1,20 +0,0 @@
language: rust
rust:
- stable
- beta
- nightly
matrix:
allow_failures:
- rust: nightly
after_success:
- |-
[ $TRAVIS_BRANCH = master ] &&
[ $TRAVIS_PULL_REQUEST = false ] &&
cargo doc --all --no-deps &&
echo '<meta http-equiv=refresh content=0;url=parity_tokio_ipc/index.html>' > target/doc/index.html &&
pip install --user ghp-import &&
/home/travis/.local/bin/ghp-import -n target/doc &&
git push -fq https://${TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
env:
global:
secure: eUHPLjVMSVclRcEgwgybIKZQJTBW8QDjcjgIsEhOHZn7Kpzw0+rwJVoKkvr/uqyJwyY7pHy36mWX31J8YDSbSiM3W8jXeI97sk+FTUkleqUffPzXnbnR1D4kHZlKndFIbcuO5Z+rtVgsAv5E/u1w9XR+mvgK2lfaIEay+26gBl6dl/1TxWvrwDBeMvfq1JGVDQH4Etubncpi3LSWhbRkie1AKnVnsDIY9sUYVKSnIqjxx0qW6Z7EiCdwZ8gf04LNnqyIoKDpyldotL+nJ67ZlVI2O2DrbOOt55nliFHsH4BcWZIZOyIAM4PxIwhDl8g9E55FLkkUX9VUpVtqjTu9RWkVl7rzyrSxLoBUEjguIPrpFWBwLo0FSDvplB2XCXt8x035Io5PEg6m5dVxx5iytTIbI6HQwcA0ESTuDPuAdRJMNvJS/9e2UzPukdYYaaxF6g8wSmiIQjLuZU/nGBdmAl7Uw6cFlQnyLc/GXQg0oZ+B/J8sc4W2C/Z64oB8jK72RLNTKeeWs/XSOt8NxQiNkWeFIhGqiYOPJgjBiTCLSKJPY3CUTiBT8QpAcpj1x1gsWi+5fRoXYxNig/CmeTwZjuxKNxfQIu3J+lJbNdt44x7whnwhZ/AKVuLFPNNiC2OBNpa738UY60VYDoNZyhomWSdBnz3E6i1VtdiSnujFFnc=

View File

@@ -1,24 +0,0 @@
[package]
name = "parity-tokio-ipc"
version = "0.7.2"
edition = "2018"
authors = ["NikVolf <nikvolf@gmail.com>"]
license = "MIT/Apache-2.0"
readme = "README.md"
repository = "https://github.com/nikvolf/parity-tokio-ipc"
homepage = "https://github.com/nikvolf/parity-tokio-ipc"
description = """
Interprocess communication library for tokio.
"""
[dependencies]
futures = "0.3"
log = "0.4"
mio-named-pipes = "0.1"
miow = "0.3"
rand = "0.7"
tokio = { version = "0.2", features = ["io-driver", "io-util", "uds", "stream", "rt-core", "macros", "time"] }
libc = "0.2"
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["winbase", "winnt", "accctrl", "aclapi", "securitybaseapi", "minwinbase", "winbase"] }

View File

@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,25 +0,0 @@
Copyright (c) 2017 Nikolay Volf
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@@ -1,28 +0,0 @@
# parity-tokio-ipc
[![Build Status](https://travis-ci.org/NikVolf/parity-tokio-ipc.svg?branch=master)](https://travis-ci.org/NikVolf/parity-tokio-ipc)
[Documentation](https://nikvolf.github.io/parity-tokio-ipc)
This crate abstracts interprocess transport for UNIX/Windows. On UNIX it utilizes unix sockets (`tokio_uds` crate) and named pipe on windows (experimental `tokio-named-pipes` crate).
Endpoint is transport-agnostic interface for incoming connections:
```rust
let endpoint = Endpoint::new(endpoint_addr, handle).unwrap();
endpoint.incoming().for_each(|_| println!("Connection received!"));
```
And IpcStream is transport-agnostic io:
```rust
let endpoint = Endpoint::new(endpoint_addr, handle).unwrap();
endpoint.incoming().for_each(|(ipc_stream: IpcStream, _)| io::write_all(ipc_stream, b"Hello!"));
```
# License
`parity-tokio-ipc` is primarily distributed under the terms of both the MIT
license and the Apache License (Version 2.0), with portions covered by various
BSD-like licenses.
See LICENSE-APACHE, and LICENSE-MIT for details.

View File

@@ -1,16 +0,0 @@
environment:
matrix:
- TARGET: x86_64-pc-windows-msvc
install:
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
- rustup-init.exe -y --default-host %TARGET%
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin;C:\MinGW\bin
- rustc -vV
- cargo -vV
build: false
test_script:
- cargo test

View File

@@ -1,24 +0,0 @@
use tokio::{self, prelude::*};
use parity_tokio_ipc::Endpoint;
#[tokio::main]
async fn main() {
let path = std::env::args().nth(1).expect("Run it with server path to connect as argument");
let mut client = Endpoint::connect(&path).await
.expect("Failed to connect client.");
loop {
let mut buf = [0u8; 4];
println!("SEND: PING");
client.write_all(b"ping").await.expect("Unable to write message to client");
client.read_exact(&mut buf[..]).await.expect("Unable to read buffer");
if let Ok("pong") = std::str::from_utf8(&buf[..]) {
println!("RECEIVED: PONG");
} else {
break;
}
tokio::time::delay_for(std::time::Duration::from_secs(2)).await;
}
}

View File

@@ -1,47 +0,0 @@
use futures::StreamExt as _;
use tokio::{
prelude::*,
self,
io::split,
};
use parity_tokio_ipc::{Endpoint, SecurityAttributes};
async fn run_server(path: String) {
let mut endpoint = Endpoint::new(path);
endpoint.set_security_attributes(SecurityAttributes::allow_everyone_create().unwrap());
let mut incoming = endpoint.incoming().expect("failed to open new socket");
while let Some(result) = incoming.next().await
{
match result {
Ok(stream) => {
let (mut reader, mut writer) = split(stream);
tokio::spawn(async move {
loop {
let mut buf = [0u8; 4];
let pong_buf = b"pong";
if let Err(_) = reader.read_exact(&mut buf).await {
println!("Closing socket");
break;
}
if let Ok("ping") = std::str::from_utf8(&buf[..]) {
println!("RECIEVED: PING");
writer.write_all(pong_buf).await.expect("unable to write to socket");
println!("SEND: PONG");
}
}
});
}
_ => unreachable!("ideally")
}
};
}
#[tokio::main]
async fn main() {
let path = std::env::args().nth(1).expect("Run it with server path as argument");
run_server(path).await
}

View File

@@ -1,7 +0,0 @@
#!/bin/bash
echo "Spawning 100 processes"
for i in {1..100} ;
do
( cargo run --example client -- /tmp/test.ipc & )
done

View File

@@ -1,154 +0,0 @@
//! Tokio IPC transport. Under the hood uses Unix Domain Sockets for Linux/Mac
//! and Named Pipes for Windows.
//#![warn(missing_docs)]
//#![deny(rust_2018_idioms)]
#[cfg(windows)]
mod win;
#[cfg(not(windows))]
mod unix;
/// Endpoint for IPC transport
///
/// # Examples
///
/// ```ignore
/// use parity_tokio_ipc::{Endpoint, dummy_endpoint};
/// use futures::{future, Future, Stream, StreamExt};
/// use tokio::runtime::Runtime;
///
/// fn main() {
/// let mut runtime = Runtime::new().unwrap();
/// let mut endpoint = Endpoint::new(dummy_endpoint());
/// let server = endpoint.incoming()
/// .expect("failed to open up a new pipe/socket")
/// .for_each(|_stream| {
/// println!("Connection received");
/// futures::future::ready(())
/// });
/// runtime.block_on(server)
/// }
///```
#[cfg(windows)]
pub use win::{SecurityAttributes, Endpoint, Connection, Incoming};
#[cfg(unix)]
pub use unix::{SecurityAttributes, Endpoint, Connection, Incoming};
/// For testing/examples
pub fn dummy_endpoint() -> String {
let num: u64 = rand::Rng::gen(&mut rand::thread_rng());
if cfg!(windows) {
format!(r"\\.\pipe\my-pipe-{}", num)
} else {
format!(r"/tmp/my-uds-{}", num)
}
}
#[cfg(test)]
mod tests {
use tokio::prelude::*;
use futures::{channel::oneshot, StreamExt as _, FutureExt as _};
use std::time::Duration;
use tokio::{
self,
io::split,
};
use super::{dummy_endpoint, Endpoint, SecurityAttributes};
use std::path::Path;
use futures::future::{Either, select, ready};
async fn run_server(path: String) {
let path = path.to_owned();
let mut endpoint = Endpoint::new(path);
endpoint.set_security_attributes(
SecurityAttributes::empty()
.set_mode(0o777)
.unwrap()
);
let mut incoming = endpoint.incoming().expect("failed to open up a new socket");
while let Some(result) = incoming.next().await {
match result {
Ok(stream) => {
let (mut reader, mut writer) = split(stream);
let mut buf = [0u8; 5];
reader.read_exact(&mut buf).await.expect("unable to read from socket");
writer.write_all(&buf[..]).await.expect("unable to write to socket");
}
_ => unreachable!("ideally")
}
};
}
#[tokio::test]
async fn smoke_test() {
let path = dummy_endpoint();
let (shutdown_tx, shutdown_rx) = oneshot::channel();
let server = select(Box::pin(run_server(path.clone())), shutdown_rx)
.then(|either| {
match either {
Either::Right((_, server)) => {
drop(server);
}
_ => unreachable!("also ideally")
};
ready(())
});
tokio::spawn(server);
tokio::time::delay_for(Duration::from_secs(2)).await;
println!("Connecting to client 0...");
let mut client_0 = Endpoint::connect(&path).await
.expect("failed to open client_0");
tokio::time::delay_for(Duration::from_secs(2)).await;
println!("Connecting to client 1...");
let mut client_1 = Endpoint::connect(&path).await
.expect("failed to open client_1");
let msg = b"hello";
let mut rx_buf = vec![0u8; msg.len()];
client_0.write_all(msg).await.expect("Unable to write message to client");
client_0.read_exact(&mut rx_buf).await.expect("Unable to read message from client");
let mut rx_buf2 = vec![0u8; msg.len()];
client_1.write_all(msg).await.expect("Unable to write message to client");
client_1.read_exact(&mut rx_buf2).await.expect("Unable to read message from client");
assert_eq!(rx_buf, msg);
assert_eq!(rx_buf2, msg);
// shutdown server
if let Ok(()) = shutdown_tx.send(()) {
// wait one second for the file to be deleted.
tokio::time::delay_for(Duration::from_secs(1)).await;
let path = Path::new(&path);
// assert that it has
assert!(!path.exists());
}
}
#[cfg(windows)]
fn create_pipe_with_permissions(attr: SecurityAttributes) -> ::std::io::Result<()> {
let path = dummy_endpoint();
let mut endpoint = Endpoint::new(path);
endpoint.set_security_attributes(attr);
endpoint.incoming().map(|_| ())
}
#[cfg(windows)]
#[tokio::test]
async fn test_pipe_permissions() {
create_pipe_with_permissions(SecurityAttributes::empty())
.expect("failed with no attributes");
create_pipe_with_permissions(SecurityAttributes::allow_everyone_create().unwrap())
.expect("failed with attributes for creating");
create_pipe_with_permissions(SecurityAttributes::empty().allow_everyone_connect().unwrap())
.expect("failed with attributes for connecting");
}
}

View File

@@ -1,163 +0,0 @@
use libc::chmod;
use std::ffi::CString;
use std::io::{self, Error};
use tokio::prelude::*;
use tokio::net::{UnixListener, UnixStream};
use std::path::Path;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::mem::MaybeUninit;
/// Socket permissions and ownership on UNIX
pub struct SecurityAttributes {
// read/write permissions for owner, group and others in unix octal.
mode: Option<u16>
}
impl SecurityAttributes {
/// New default security attributes.
pub fn empty() -> Self {
SecurityAttributes {
mode: None
}
}
/// New security attributes that allow everyone to connect.
pub fn allow_everyone_connect(mut self) -> io::Result<Self> {
self.mode = Some(0o777);
Ok(self)
}
/// Set a custom permission on the socket
pub fn set_mode(mut self, mode: u16) -> io::Result<Self> {
self.mode = Some(mode);
Ok(self)
}
/// New security attributes that allow everyone to create.
pub fn allow_everyone_create() -> io::Result<Self> {
Ok(SecurityAttributes {
mode: None
})
}
/// called in unix, after server socket has been created
/// will apply security attributes to the socket.
pub(crate) unsafe fn apply_permissions(&self, path: &str) -> io::Result<()> {
let path = CString::new(path.to_owned())?;
if let Some(mode) = self.mode {
if chmod(path.as_ptr(), mode as _) == -1 {
return Err(Error::last_os_error())
}
}
Ok(())
}
}
/// Endpoint implementation for unix systems
pub struct Endpoint {
path: String,
security_attributes: SecurityAttributes,
}
pub struct Incoming {
socket: UnixListener,
}
impl Incoming {
pub async fn next(&mut self) -> Option<io::Result<Connection>> {
match self.socket.accept().await {
Ok((stream, _)) => Some(Ok(Connection::wrap(stream))),
Err(err) => Some(Err(err))
}
}
}
impl Endpoint {
/// Stream of incoming connections
pub fn incoming(&mut self) -> io::Result<Incoming> {
unsafe {
// the call to bind in `inner()` creates the file
// `apply_permission()` will set the file permissions.
self.security_attributes.apply_permissions(&self.path)?;
};
let socket = self.inner()?;
Ok(Incoming { socket })
}
/// Inner platform-dependant state of the endpoint
fn inner(&self) -> io::Result<UnixListener> {
UnixListener::bind(&self.path)
}
/// Set security attributes for the connection
pub fn set_security_attributes(&mut self, security_attributes: SecurityAttributes) {
self.security_attributes = security_attributes;
}
/// Make new connection using the provided path and running event pool
pub async fn connect<P: AsRef<Path>>(path: P) -> io::Result<Connection> {
Ok(Connection::wrap(UnixStream::connect(path.as_ref()).await?))
}
/// Returns the path of the endpoint.
pub fn path(&self) -> &str {
&self.path
}
/// New IPC endpoint at the given path
pub fn new(path: String) -> Self {
Endpoint {
path,
security_attributes: SecurityAttributes::empty(),
}
}
}
/// IPC connection.
pub struct Connection {
inner: UnixStream,
}
impl Connection {
fn wrap(stream: UnixStream) -> Self {
Self { inner: stream }
}
}
impl AsyncRead for Connection {
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [MaybeUninit<u8>]) -> bool {
self.inner.prepare_uninitialized_buffer(buf)
}
fn poll_read(
self: Pin<&mut Self>,
ctx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
let this = Pin::into_inner(self);
Pin::new(&mut this.inner).poll_read(ctx, buf)
}
}
impl AsyncWrite for Connection {
fn poll_write(
self: Pin<&mut Self>,
ctx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize, io::Error>> {
let this = Pin::into_inner(self);
Pin::new(&mut this.inner).poll_write(ctx, buf)
}
fn poll_flush(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
let this = Pin::into_inner(self);
Pin::new(&mut this.inner).poll_flush(ctx)
}
fn poll_shutdown(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
let this = Pin::into_inner(self);
Pin::new(&mut this.inner).poll_shutdown(ctx)
}
}

View File

@@ -1,488 +0,0 @@
use winapi::shared::winerror::ERROR_SUCCESS;
use winapi::um::accctrl::*;
use winapi::um::aclapi::*;
use winapi::um::minwinbase::{LPTR, PSECURITY_ATTRIBUTES, SECURITY_ATTRIBUTES};
use winapi::um::securitybaseapi::*;
use winapi::um::winbase::{LocalAlloc, LocalFree};
use winapi::um::winnt::*;
use std::io;
use std::marker;
use std::mem;
use std::ptr;
use futures::Stream;
use tokio::prelude::*;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::path::Path;
use std::mem::MaybeUninit;
use tokio::io::PollEvented;
type NamedPipe = PollEvented<mio_named_pipes::NamedPipe>;
const PIPE_AVAILABILITY_TIMEOUT: u64 = 5000;
/// Endpoint implementation for windows
pub struct Endpoint {
path: String,
security_attributes: SecurityAttributes,
}
impl Endpoint {
/// Stream of incoming connections
pub fn incoming(mut self) -> io::Result<Incoming> {
let pipe = self.inner()?;
Ok(Incoming {
path: self.path.clone(),
inner: NamedPipeSupport {
path: self.path,
pipe,
security_attributes: self.security_attributes,
},
})
}
/// Inner platform-dependant state of the endpoint
fn inner(&mut self) -> io::Result<NamedPipe> {
use miow::pipe::NamedPipeBuilder;
use std::os::windows::io::*;
let raw_handle = unsafe {
NamedPipeBuilder::new(&self.path)
.first(true)
.inbound(true)
.outbound(true)
.out_buffer_size(65536)
.in_buffer_size(65536)
.with_security_attributes(self.security_attributes.as_ptr())?
.into_raw_handle()
};
let mio_pipe = unsafe { mio_named_pipes::NamedPipe::from_raw_handle(raw_handle) };
NamedPipe::new(mio_pipe)
}
/// Set security attributes for the connection
pub fn set_security_attributes(&mut self, security_attributes: SecurityAttributes) {
self.security_attributes = security_attributes;
}
/// Returns the path of the endpoint.
pub fn path(&self) -> &str {
&self.path
}
/// Make new connection using the provided path and running event pool.
pub async fn connect<P: AsRef<Path>>(path: P) -> io::Result<Connection> {
Ok(Connection::wrap(Self::connect_inner(path.as_ref())?))
}
fn connect_inner(path: &Path) -> io::Result<NamedPipe> {
use std::fs::OpenOptions;
use std::os::windows::fs::OpenOptionsExt;
use std::os::windows::io::{FromRawHandle, IntoRawHandle};
use winapi::um::winbase::FILE_FLAG_OVERLAPPED;
// Wait for the pipe to become available or fail after 5 seconds.
miow::pipe::NamedPipe::wait(
path,
Some(std::time::Duration::from_millis(PIPE_AVAILABILITY_TIMEOUT)),
)?;
let file = OpenOptions::new()
.read(true)
.write(true)
.custom_flags(FILE_FLAG_OVERLAPPED)
.open(path)?;
let mio_pipe =
unsafe { mio_named_pipes::NamedPipe::from_raw_handle(file.into_raw_handle()) };
let pipe = NamedPipe::new(mio_pipe)?;
Ok(pipe)
}
/// New IPC endpoint at the given path
pub fn new(path: String) -> Self {
Endpoint {
path,
security_attributes: SecurityAttributes::empty(),
}
}
}
struct NamedPipeSupport {
path: String,
pipe: NamedPipe,
security_attributes: SecurityAttributes,
}
impl NamedPipeSupport {
fn replacement_pipe(&mut self) -> io::Result<NamedPipe> {
use miow::pipe::NamedPipeBuilder;
use std::os::windows::io::*;
let raw_handle = unsafe {
NamedPipeBuilder::new(&self.path)
.first(false)
.inbound(true)
.outbound(true)
.out_buffer_size(65536)
.in_buffer_size(65536)
.with_security_attributes(self.security_attributes.as_ptr())?
.into_raw_handle()
};
let mio_pipe = unsafe { mio_named_pipes::NamedPipe::from_raw_handle(raw_handle) };
NamedPipe::new(mio_pipe)
}
}
/// Stream of incoming connections
pub struct Incoming {
#[allow(dead_code)]
path: String,
inner: NamedPipeSupport,
}
impl Stream for Incoming {
type Item = tokio::io::Result<Connection>;
fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
match self.inner.pipe.get_ref().connect() {
Ok(()) => {
log::trace!("Incoming connection polled successfully");
let new_listener = self.inner.replacement_pipe()?;
Poll::Ready(
Some(Ok(Connection::wrap(std::mem::replace(&mut self.inner.pipe, new_listener))))
)
}
Err(e) => {
if e.kind() == io::ErrorKind::WouldBlock {
self.inner.pipe.clear_write_ready(ctx);
Poll::Pending
} else {
Poll::Ready(Some(Err(e)))
}
}
}
}
}
/// IPC connection.
pub struct Connection {
inner: NamedPipe,
}
impl Connection {
pub fn wrap(pipe: NamedPipe) -> Self {
Self { inner: pipe }
}
}
impl AsyncRead for Connection {
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [MaybeUninit<u8>]) -> bool {
self.inner.prepare_uninitialized_buffer(buf)
}
fn poll_read(
self: Pin<&mut Self>,
ctx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
let this = Pin::into_inner(self);
Pin::new(&mut this.inner).poll_read(ctx, buf)
}
}
impl AsyncWrite for Connection {
fn poll_write(
self: Pin<&mut Self>,
ctx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize, io::Error>> {
let this = Pin::into_inner(self);
Pin::new(&mut this.inner).poll_write(ctx, buf)
}
fn poll_flush(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
let this = Pin::into_inner(self);
Pin::new(&mut this.inner).poll_flush(ctx)
}
fn poll_shutdown(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
let this = Pin::into_inner(self);
Pin::new(&mut this.inner).poll_shutdown(ctx)
}
}
/// Security attributes.
pub struct SecurityAttributes {
attributes: Option<InnerAttributes>,
}
impl SecurityAttributes {
/// New default security attributes.
pub fn empty() -> SecurityAttributes {
SecurityAttributes { attributes: None }
}
/// New default security attributes that allow everyone to connect.
pub fn allow_everyone_connect(&self) -> io::Result<SecurityAttributes> {
let attributes = Some(InnerAttributes::allow_everyone(
GENERIC_READ | FILE_WRITE_DATA,
)?);
Ok(SecurityAttributes { attributes })
}
/// Set a custom permission on the socket
pub fn set_mode(self, _mode: u32) -> io::Result<Self> {
// for now, does nothing.
Ok(self)
}
/// New default security attributes that allow everyone to create.
pub fn allow_everyone_create() -> io::Result<SecurityAttributes> {
let attributes = Some(InnerAttributes::allow_everyone(
GENERIC_READ | GENERIC_WRITE,
)?);
Ok(SecurityAttributes { attributes })
}
/// Return raw handle of security attributes.
pub(crate) unsafe fn as_ptr(&mut self) -> PSECURITY_ATTRIBUTES {
match self.attributes.as_mut() {
Some(attributes) => attributes.as_ptr(),
None => ptr::null_mut(),
}
}
}
unsafe impl Send for SecurityAttributes {}
struct Sid {
sid_ptr: PSID,
}
impl Sid {
fn everyone_sid() -> io::Result<Sid> {
let mut sid_ptr = ptr::null_mut();
let result = unsafe {
AllocateAndInitializeSid(
SECURITY_WORLD_SID_AUTHORITY.as_mut_ptr() as *mut _,
1,
SECURITY_WORLD_RID,
0,
0,
0,
0,
0,
0,
0,
&mut sid_ptr,
)
};
if result == 0 {
Err(io::Error::last_os_error())
} else {
Ok(Sid { sid_ptr })
}
}
// Unsafe - the returned pointer is only valid for the lifetime of self.
unsafe fn as_ptr(&self) -> PSID {
self.sid_ptr
}
}
impl Drop for Sid {
fn drop(&mut self) {
if !self.sid_ptr.is_null() {
unsafe {
FreeSid(self.sid_ptr);
}
}
}
}
struct AceWithSid<'a> {
explicit_access: EXPLICIT_ACCESS_W,
_marker: marker::PhantomData<&'a Sid>,
}
impl<'a> AceWithSid<'a> {
fn new(sid: &'a Sid, trustee_type: u32) -> AceWithSid<'a> {
let mut explicit_access = unsafe { mem::zeroed::<EXPLICIT_ACCESS_W>() };
explicit_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
explicit_access.Trustee.TrusteeType = trustee_type;
explicit_access.Trustee.ptstrName = unsafe { sid.as_ptr() as *mut _ };
AceWithSid {
explicit_access,
_marker: marker::PhantomData,
}
}
fn set_access_mode(&mut self, access_mode: u32) -> &mut Self {
self.explicit_access.grfAccessMode = access_mode;
self
}
fn set_access_permissions(&mut self, access_permissions: u32) -> &mut Self {
self.explicit_access.grfAccessPermissions = access_permissions;
self
}
fn allow_inheritance(&mut self, inheritance_flags: u32) -> &mut Self {
self.explicit_access.grfInheritance = inheritance_flags;
self
}
}
struct Acl {
acl_ptr: PACL,
}
impl Acl {
fn empty() -> io::Result<Acl> {
Self::new(&mut [])
}
fn new(entries: &mut [AceWithSid<'_>]) -> io::Result<Acl> {
let mut acl_ptr = ptr::null_mut();
let result = unsafe {
SetEntriesInAclW(
entries.len() as u32,
entries.as_mut_ptr() as *mut _,
ptr::null_mut(),
&mut acl_ptr,
)
};
if result != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(result as i32));
}
Ok(Acl { acl_ptr })
}
unsafe fn as_ptr(&self) -> PACL {
self.acl_ptr
}
}
impl Drop for Acl {
fn drop(&mut self) {
if !self.acl_ptr.is_null() {
unsafe { LocalFree(self.acl_ptr as *mut _) };
}
}
}
struct SecurityDescriptor {
descriptor_ptr: PSECURITY_DESCRIPTOR,
}
impl SecurityDescriptor {
fn new() -> io::Result<Self> {
let descriptor_ptr = unsafe { LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH) };
if descriptor_ptr.is_null() {
return Err(io::Error::new(
io::ErrorKind::Other,
"Failed to allocate security descriptor",
));
}
if unsafe {
InitializeSecurityDescriptor(descriptor_ptr, SECURITY_DESCRIPTOR_REVISION) == 0
} {
return Err(io::Error::last_os_error());
};
Ok(SecurityDescriptor { descriptor_ptr })
}
fn set_dacl(&mut self, acl: &Acl) -> io::Result<()> {
if unsafe {
SetSecurityDescriptorDacl(self.descriptor_ptr, true as i32, acl.as_ptr(), false as i32)
== 0
} {
return Err(io::Error::last_os_error());
}
Ok(())
}
unsafe fn as_ptr(&self) -> PSECURITY_DESCRIPTOR {
self.descriptor_ptr
}
}
impl Drop for SecurityDescriptor {
fn drop(&mut self) {
if !self.descriptor_ptr.is_null() {
unsafe { LocalFree(self.descriptor_ptr) };
self.descriptor_ptr = ptr::null_mut();
}
}
}
struct InnerAttributes {
descriptor: SecurityDescriptor,
acl: Acl,
attrs: SECURITY_ATTRIBUTES,
}
impl InnerAttributes {
fn empty() -> io::Result<InnerAttributes> {
let descriptor = SecurityDescriptor::new()?;
let mut attrs = unsafe { mem::zeroed::<SECURITY_ATTRIBUTES>() };
attrs.nLength = mem::size_of::<SECURITY_ATTRIBUTES>() as u32;
attrs.lpSecurityDescriptor = unsafe { descriptor.as_ptr() };
attrs.bInheritHandle = false as i32;
let acl = Acl::empty().expect("this should never fail");
Ok(InnerAttributes {
acl,
descriptor,
attrs,
})
}
fn allow_everyone(permissions: u32) -> io::Result<InnerAttributes> {
let mut attributes = Self::empty()?;
let sid = Sid::everyone_sid()?;
let mut everyone_ace = AceWithSid::new(&sid, TRUSTEE_IS_WELL_KNOWN_GROUP);
everyone_ace
.set_access_mode(SET_ACCESS)
.set_access_permissions(permissions)
.allow_inheritance(false as u32);
let mut entries = vec![everyone_ace];
attributes.acl = Acl::new(&mut entries)?;
attributes.descriptor.set_dacl(&attributes.acl)?;
Ok(attributes)
}
unsafe fn as_ptr(&mut self) -> PSECURITY_ATTRIBUTES {
&mut self.attrs as *mut _
}
}
#[cfg(test)]
mod test {
use super::SecurityAttributes;
#[test]
fn test_allow_everyone_everything() {
SecurityAttributes::allow_everyone_create()
.expect("failed to create security attributes that allow everyone to create a pipe");
}
#[test]
fn test_allow_eveyone_read_write() {
SecurityAttributes::empty()
.allow_everyone_connect()
.expect("failed to create security attributes that allow everyone to read and write to/from a pipe");
}
}

View File

@@ -1,4 +0,0 @@
**/target
/target
**/*.rs.bk
.idea/

129
libs/pulsectl/Cargo.lock generated
View File

@@ -1,129 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "libc"
version = "0.2.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
[[package]]
name = "libpulse-binding"
version = "2.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe925a4d3a96961316c9c1488f97a95938a6093f0d4691eec888776057ce965e"
dependencies = [
"libc",
"libpulse-sys",
"num-derive",
"num-traits",
"winapi",
]
[[package]]
name = "libpulse-sys"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d9073c83dda6aff9b611dc368e8db6e0aa29027546d8800a18b4417e182b4d5"
dependencies = [
"libc",
"num-derive",
"num-traits",
"pkg-config",
"winapi",
]
[[package]]
name = "num-derive"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "pkg-config"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rust-pulsectl"
version = "0.2.9"
dependencies = [
"libpulse-binding",
]
[[package]]
name = "syn"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b4f34193997d92804d359ed09953e25d5138df6bcc055a71bf68ee89fdf9223"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@@ -1,19 +0,0 @@
[package]
name = "rust-pulsectl"
version = "0.2.10"
authors = ["Kristopher Ruzic <krruzic@gmail.com>"]
edition = "2018"
license = "GPL-3.0+"
description = "A higher level API for libpulse_binding"
readme = "README.md"
keywords = ["pulse", "pulseaudio", "binding", "audio", "api"]
categories = ["api-bindings", "multimedia::audio"]
homepage = "https://github.com/krruzic/pulsectl"
repository = "https://github.com/krruzic/pulsectl"
[lib]
name = "pulsectl"
path = "src/lib.rs"
[dependencies]
libpulse-binding = "2.21"

Some files were not shown because too many files have changed in this diff Show More