tabby-rdp 0.2.7 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +72 -2
- package/README.md +182 -21
- package/dist/connectionStatus.js +140 -0
- package/dist/connectionStatus.js.map +1 -0
- package/dist/desk.js +21 -10
- package/dist/desk.js.map +1 -1
- package/dist/deskScript.js +3 -0
- package/dist/deskScript.js.map +1 -1
- package/dist/desktop.service.js +994 -53
- package/dist/desktop.service.js.map +1 -1
- package/dist/desktopForm.js +64 -19
- package/dist/desktopForm.js.map +1 -1
- package/dist/desktops.js +60 -21
- package/dist/desktops.js.map +1 -1
- package/dist/fileTransfer.js +152 -5
- package/dist/fileTransfer.js.map +1 -1
- package/dist/header.js +22 -7
- package/dist/header.js.map +1 -1
- package/dist/help.js +241 -0
- package/dist/help.js.map +1 -0
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/keyboard.js +142 -5
- package/dist/keyboard.js.map +1 -1
- package/dist/microphone.js +295 -0
- package/dist/microphone.js.map +1 -0
- package/dist/osd.js +79 -0
- package/dist/osd.js.map +1 -0
- package/dist/probe.js +33 -0
- package/dist/probe.js.map +1 -0
- package/dist/rdcleanpath.js +132 -7
- package/dist/rdcleanpath.js.map +1 -1
- package/dist/rdpFile.js +47 -0
- package/dist/rdpFile.js.map +1 -0
- package/dist/rdpProfile.js +367 -0
- package/dist/rdpProfile.js.map +1 -0
- package/dist/remoteSetup.js +90 -11
- package/dist/remoteSetup.js.map +1 -1
- package/dist/settingsPage.js +554 -0
- package/dist/settingsPage.js.map +1 -0
- package/dist/signin.js +21 -2
- package/dist/signin.js.map +1 -1
- package/dist/ssh.js +28 -0
- package/dist/ssh.js.map +1 -1
- package/dist/targets.js +148 -8
- package/dist/targets.js.map +1 -1
- package/dist/ui.js +163 -24
- package/dist/ui.js.map +1 -1
- package/dist/updates.js +123 -0
- package/dist/updates.js.map +1 -0
- package/dist/vms.js +90 -0
- package/dist/vms.js.map +1 -0
- package/dist/wake.js +124 -0
- package/dist/wake.js.map +1 -0
- package/package.json +2 -1
- package/vendor/IRONRDP-LICENSE +3 -3
- package/vendor/iron-remote-desktop-rdp.js +698 -451
- package/vendor/iron-remote-desktop.js +87 -81
- package/vendor/ironrdp_web_bg.wasm +0 -0
package/dist/wake.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseWake = parseWake;
|
|
4
|
+
exports.wakeFromText = wakeFromText;
|
|
5
|
+
exports.rdpAnswers = rdpAnswers;
|
|
6
|
+
exports.wakeDesktop = wakeDesktop;
|
|
7
|
+
exports.waitForRdp = waitForRdp;
|
|
8
|
+
const deskScript_1 = require("./deskScript");
|
|
9
|
+
const MAC = /^[0-9a-f]{2}([:-]?)[0-9a-f]{2}(\1[0-9a-f]{2}){4}$/i;
|
|
10
|
+
const IPV4 = /^\d{1,3}(\.\d{1,3}){3}$/;
|
|
11
|
+
/** A `wake` config value, checked; undefined when absent or unusable. */
|
|
12
|
+
function parseWake(raw) {
|
|
13
|
+
if (typeof raw?.vm === 'string' && raw.vm.trim()) {
|
|
14
|
+
return { vm: raw.vm.trim() };
|
|
15
|
+
}
|
|
16
|
+
const mac = typeof raw?.mac === 'string' ? raw.mac.trim() : '';
|
|
17
|
+
if (MAC.test(mac)) {
|
|
18
|
+
const port = Number(raw.port ?? 9);
|
|
19
|
+
return {
|
|
20
|
+
mac,
|
|
21
|
+
...typeof raw.broadcast === 'string' && IPV4.test(raw.broadcast.trim()) ? { broadcast: raw.broadcast.trim() } : {},
|
|
22
|
+
...Number.isInteger(port) && port > 0 && port < 65536 && port !== 9 ? { port } : {},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
/** The add-desktop form's wake field: a MAC address means Wake-on-LAN, anything else names a libvirt VM. */
|
|
28
|
+
function wakeFromText(text) {
|
|
29
|
+
const value = text.trim();
|
|
30
|
+
return !value ? undefined : MAC.test(value) ? { mac: value } : { vm: value };
|
|
31
|
+
}
|
|
32
|
+
// Whether an RDP server answers at $H:$P, as seen from the SSH host: an X.224 connection request must get a TPKT
|
|
33
|
+
// reply, since a port can accept connections before the server behind it does (QEMU's user-mode port forwarding,
|
|
34
|
+
// for one). Without python3, an open TCP port will do.
|
|
35
|
+
const PROBE_SCRIPT = String.raw `
|
|
36
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
37
|
+
python3 -c '
|
|
38
|
+
import socket, sys
|
|
39
|
+
try:
|
|
40
|
+
s = socket.create_connection((sys.argv[1], int(sys.argv[2])), 3)
|
|
41
|
+
s.settimeout(3)
|
|
42
|
+
s.sendall(bytes.fromhex("030000130ee000000000000100080003000000"))
|
|
43
|
+
print("RD_OPEN" if s.recv(2) == b"\x03\x00" else "RD_CLOSED")
|
|
44
|
+
except Exception:
|
|
45
|
+
print("RD_CLOSED")
|
|
46
|
+
' "$H" "$P"
|
|
47
|
+
elif command -v nc >/dev/null 2>&1; then
|
|
48
|
+
nc -z -w 3 "$H" "$P" >/dev/null 2>&1 && echo RD_OPEN || echo RD_CLOSED
|
|
49
|
+
else
|
|
50
|
+
timeout 3 bash -c 'exec 3<>"/dev/tcp/$0/$1"' "$H" "$P" >/dev/null 2>&1 && echo RD_OPEN || echo RD_CLOSED
|
|
51
|
+
fi
|
|
52
|
+
`;
|
|
53
|
+
// Starts (or resumes) the libvirt domain $VM as the SSH user: the system instance first, where VMs usually are
|
|
54
|
+
// (needs the libvirt group or polkit), then the user's own session instance.
|
|
55
|
+
const VM_SCRIPT = String.raw `
|
|
56
|
+
command -v virsh >/dev/null 2>&1 || { echo "RD_ERR virsh is not installed on the SSH host"; exit 0; }
|
|
57
|
+
errors=""
|
|
58
|
+
for uri in qemu:///system qemu:///session; do
|
|
59
|
+
if ! state=$(virsh -c "$uri" domstate "$VM" 2>&1); then
|
|
60
|
+
errors="$errors${"$"}{errors:+; }$uri: $(printf '%s' "$state" | tr '\n' ' ' | sed 's/^error: //' | cut -c1-160)"
|
|
61
|
+
continue
|
|
62
|
+
fi
|
|
63
|
+
case $(printf '%s\n' "$state" | head -n 1) in
|
|
64
|
+
running) echo "RD_OK $VM is already running ($uri)"; exit 0 ;;
|
|
65
|
+
paused) how=resumed; out=$(virsh -c "$uri" resume "$VM" 2>&1) ;;
|
|
66
|
+
pmsuspended) how="woken up"; out=$(virsh -c "$uri" dompmwakeup "$VM" 2>&1) ;;
|
|
67
|
+
*) how=started; out=$(virsh -c "$uri" start "$VM" 2>&1) ;;
|
|
68
|
+
esac && { echo "RD_OK $VM $how ($uri)"; exit 0; }
|
|
69
|
+
echo "RD_ERR virsh: $(printf '%s' "$out" | tr '\n' ' ' | sed 's/^error: //' | cut -c1-240)"
|
|
70
|
+
exit 0
|
|
71
|
+
done
|
|
72
|
+
echo "RD_ERR no libvirt VM named $VM for this user ($errors)"
|
|
73
|
+
`;
|
|
74
|
+
// A Wake-on-LAN magic packet ($MAC 16 times after 6 bytes of 0xff) to $BCAST:$PORT, with the standard library.
|
|
75
|
+
const WOL_SCRIPT = String.raw `
|
|
76
|
+
command -v python3 >/dev/null 2>&1 || { echo "RD_ERR sending Wake-on-LAN needs python3 on the SSH host"; exit 0; }
|
|
77
|
+
python3 -c '
|
|
78
|
+
import socket, sys
|
|
79
|
+
mac = bytes.fromhex(sys.argv[1].replace(":", "").replace("-", ""))
|
|
80
|
+
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
81
|
+
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
|
82
|
+
s.sendto(b"\xff" * 6 + mac * 16, (sys.argv[2], int(sys.argv[3])))
|
|
83
|
+
print("RD_OK Wake-on-LAN sent to %s via %s:%s" % tuple(sys.argv[1:4]))
|
|
84
|
+
' "$MAC" "$BCAST" "$PORT" 2>&1 || echo "RD_ERR could not send the Wake-on-LAN packet"
|
|
85
|
+
`;
|
|
86
|
+
/** Whether the RDP server at host:port answers, as seen from the SSH host. */
|
|
87
|
+
async function rdpAnswers(target, host, port) {
|
|
88
|
+
const out = await target.exec('sh -s', `H=${(0, deskScript_1.shq)(host)}\nP=${port}\n${PROBE_SCRIPT}`);
|
|
89
|
+
return /^RD_OPEN$/m.test(out);
|
|
90
|
+
}
|
|
91
|
+
/** Starts the desktop as `wake` says. Resolves with what was done; throws with the reason when it couldn't. */
|
|
92
|
+
async function wakeDesktop(target, wake) {
|
|
93
|
+
const script = 'vm' in wake
|
|
94
|
+
? `VM=${(0, deskScript_1.shq)(wake.vm)}\n${VM_SCRIPT}`
|
|
95
|
+
: `MAC=${(0, deskScript_1.shq)(wake.mac)}\nBCAST=${(0, deskScript_1.shq)(wake.broadcast ?? '255.255.255.255')}\nPORT=${wake.port ?? 9}\n${WOL_SCRIPT}`;
|
|
96
|
+
const out = await target.exec('sh -s', script);
|
|
97
|
+
const err = /^RD_ERR (.*)$/m.exec(out);
|
|
98
|
+
if (err) {
|
|
99
|
+
throw new Error(err[1].trim());
|
|
100
|
+
}
|
|
101
|
+
return /^RD_OK (.*)$/m.exec(out)?.[1] ?? 'no result';
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Probes until the RDP server answers (true), the time is up or `stopped()` (false). At most one probe every
|
|
105
|
+
* 3 s; `progress` is called every 5 s.
|
|
106
|
+
*/
|
|
107
|
+
async function waitForRdp(target, host, port, timeoutMs, stopped, progress) {
|
|
108
|
+
const deadline = Date.now() + timeoutMs;
|
|
109
|
+
const ticker = setInterval(() => stopped() || progress(), 5000);
|
|
110
|
+
try {
|
|
111
|
+
while (Date.now() < deadline && !stopped()) {
|
|
112
|
+
const started = Date.now();
|
|
113
|
+
if (await rdpAnswers(target, host, port).catch(() => false)) {
|
|
114
|
+
return !stopped();
|
|
115
|
+
}
|
|
116
|
+
await new Promise(resolve => setTimeout(resolve, Math.max(0, 3000 - (Date.now() - started))));
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
clearInterval(ticker);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=wake.js.map
|
package/dist/wake.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wake.js","sourceRoot":"","sources":["../src/wake.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tabby-rdp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Remote desktops in Tabby's SSH tabs: Linux (GNOME) and Windows, through the SSH connection, with clipboard, files and sound. Built on IronRDP.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tabby-plugin",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"@types/node": "^20.19.0",
|
|
50
50
|
"rxjs": "7.8.2",
|
|
51
51
|
"tabby-core": "1.0.231-nightly.0",
|
|
52
|
+
"tabby-settings": "1.0.231-nightly.0",
|
|
52
53
|
"tabby-terminal": "1.0.231-nightly.0",
|
|
53
54
|
"typescript": "~5.9.3"
|
|
54
55
|
}
|
package/vendor/IRONRDP-LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
vendor/iron-remote-desktop*.js are built from IronRDP
|
|
2
|
-
9b151c4c2e47c6014e1e8e55909d4180aa8bdb99 with the patches in
|
|
3
|
-
its MIT license follows.
|
|
1
|
+
vendor/iron-remote-desktop*.js and vendor/ironrdp_web_bg.wasm are built from IronRDP
|
|
2
|
+
(https://github.com/Devolutions/IronRDP) at commit 9b151c4c2e47c6014e1e8e55909d4180aa8bdb99 with the patches in
|
|
3
|
+
ironrdp/patches applied. IronRDP is dual-licensed under MIT or Apache-2.0; its MIT license follows.
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any
|
|
6
6
|
person obtaining a copy of this software and associated
|