mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-12-11 17:59:15 +08:00
more api
This commit is contained in:
parent
2846804234
commit
f4c3198037
@ -15,6 +15,7 @@
|
||||
"libsodium": "^0.7.9",
|
||||
"libsodium-wrappers": "^0.7.9",
|
||||
"ogv": "^1.8.6",
|
||||
"ts-proto": "^1.101.0"
|
||||
"ts-proto": "^1.101.0",
|
||||
"zstddec": "^0.0.2"
|
||||
}
|
||||
}
|
||||
|
@ -19,16 +19,22 @@ export default class Connection {
|
||||
_interval: any;
|
||||
_id: string;
|
||||
_hash: message.Hash | undefined;
|
||||
_msgbox: MsgboxCallback | undefined;
|
||||
_draw: DrawCallback | undefined;
|
||||
_msgbox: MsgboxCallback;
|
||||
_draw: DrawCallback;
|
||||
_peerInfo: message.PeerInfo | undefined;
|
||||
_firstFrame: Boolean | undefined;
|
||||
_videoDecoder: any;
|
||||
_audioDecoder: any;
|
||||
_password: string | undefined;
|
||||
|
||||
constructor() {
|
||||
this._msgbox = globals.msgbox;
|
||||
this._draw = globals.draw;
|
||||
this._msgs = [];
|
||||
this._id = "";
|
||||
}
|
||||
|
||||
async start(id: string) {
|
||||
this._interval = setInterval(() => {
|
||||
while (this._msgs.length) {
|
||||
this._ws?.sendMessage(this._msgs[0]);
|
||||
@ -44,9 +50,6 @@ export default class Connection {
|
||||
this._audioDecoder = decoder;
|
||||
console.log("opus loaded");
|
||||
});
|
||||
}
|
||||
|
||||
async start(id: string) {
|
||||
const uri = getDefaultUri();
|
||||
const ws = new Websock(uri);
|
||||
this._ws = ws;
|
||||
@ -69,7 +72,7 @@ export default class Connection {
|
||||
const phr = msg.punchHoleResponse;
|
||||
const rr = msg.relayResponse;
|
||||
if (phr) {
|
||||
if (phr.failure != rendezvous.PunchHoleResponse_Failure.UNKNOWN) {
|
||||
if (phr.failure != rendezvous.PunchHoleResponse_Failure.UNRECOGNIZED) {
|
||||
switch (phr?.failure) {
|
||||
case rendezvous.PunchHoleResponse_Failure.ID_NOT_EXIST:
|
||||
this.msgbox("error", "Error", "ID does not exist");
|
||||
@ -110,7 +113,8 @@ export default class Connection {
|
||||
uuid,
|
||||
});
|
||||
ws.sendRendezvous({ requestRelay });
|
||||
await this.secure(pk);
|
||||
const secure = (await this.secure(pk)) || false;
|
||||
globals.pushEvent("connection_ready", { secure, direct: false });
|
||||
await this.msgLoop();
|
||||
}
|
||||
|
||||
@ -179,6 +183,7 @@ export default class Connection {
|
||||
});
|
||||
await this._ws?.sendMessage({ publicKey });
|
||||
this._ws?.setSecretKey(secretKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
async msgLoop() {
|
||||
@ -186,7 +191,7 @@ export default class Connection {
|
||||
const msg = this._ws?.parseMessage(await this._ws?.next());
|
||||
if (msg?.hash) {
|
||||
this._hash = msg?.hash;
|
||||
await this.handleHash();
|
||||
await this.login(this._password);
|
||||
this.msgbox("input-password", "Password Required", "");
|
||||
} else if (msg?.testDelay) {
|
||||
const testDelay = msg?.testDelay;
|
||||
@ -198,23 +203,30 @@ export default class Connection {
|
||||
if (r.error) {
|
||||
this.msgbox("error", "Error", r.error);
|
||||
} else if (r.peerInfo) {
|
||||
this._peerInfo = r.peerInfo;
|
||||
this.msgbox(
|
||||
"success",
|
||||
"Successful",
|
||||
"Connected, waiting for image..."
|
||||
);
|
||||
this.handlePeerInfo(r.peerInfo);
|
||||
}
|
||||
} else if (msg?.videoFrame) {
|
||||
this.handleVideoFrame(msg?.videoFrame!);
|
||||
} else if (msg?.clipboard) {
|
||||
const cb = msg?.clipboard;
|
||||
if (cb.compress) cb.content = globals.decompress(cb.content);
|
||||
globals.pushEvent("clipboard", cb);
|
||||
} else if (msg?.cursorData) {
|
||||
const cd = msg?.cursorData;
|
||||
cd.colors = globals.decompress(cd.colors);
|
||||
globals.pushEvent("cursor_data", cd);
|
||||
} else if (msg?.cursorId) {
|
||||
globals.pushEvent("cursor_id", { id: msg?.cursorId });
|
||||
} else if (msg?.cursorPosition) {
|
||||
globals.pushEvent("cursor_position", msg?.cursorPosition);
|
||||
} else if (msg?.misc) {
|
||||
this.handleMisc(msg?.misc);
|
||||
} else if (msg?.audioFrame) {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async handleHash() {
|
||||
await this._sendLoginMessage();
|
||||
}
|
||||
|
||||
msgbox(type_: string, title: string, text: string) {
|
||||
this._msgbox?.(type_, title, text);
|
||||
}
|
||||
@ -224,12 +236,20 @@ export default class Connection {
|
||||
}
|
||||
|
||||
close() {
|
||||
this._msgs = [];
|
||||
clearInterval(this._interval);
|
||||
this._ws?.close();
|
||||
this._videoDecoder?.close();
|
||||
this._audioDecoder?.close();
|
||||
}
|
||||
|
||||
async refresh() {
|
||||
const misc = message.Misc.fromPartial({
|
||||
refreshVideo: true,
|
||||
});
|
||||
await this._ws?.sendMessage({ misc });
|
||||
}
|
||||
|
||||
setMsgbox(callback: MsgboxCallback) {
|
||||
this._msgbox = callback;
|
||||
}
|
||||
@ -238,19 +258,27 @@ export default class Connection {
|
||||
this._draw = callback;
|
||||
}
|
||||
|
||||
async login(password: string) {
|
||||
async login(password: string | undefined, _remember: Boolean = false) {
|
||||
this._password = password;
|
||||
this.msgbox("connecting", "Connecting...", "Logging in...");
|
||||
let salt = this._hash?.salt;
|
||||
if (salt) {
|
||||
const salt = this._hash?.salt;
|
||||
if (salt && password) {
|
||||
let p = hash([password, salt]);
|
||||
let challenge = this._hash?.challenge;
|
||||
const challenge = this._hash?.challenge;
|
||||
if (challenge) {
|
||||
p = hash([p, challenge]);
|
||||
await this._sendLoginMessage(p);
|
||||
}
|
||||
} else {
|
||||
await this._sendLoginMessage();
|
||||
}
|
||||
}
|
||||
|
||||
async reconnect() {
|
||||
this.close();
|
||||
await this.start(this._id);
|
||||
}
|
||||
|
||||
async _sendLoginMessage(password: Uint8Array | undefined = undefined) {
|
||||
const loginRequest = message.LoginRequest.fromPartial({
|
||||
username: this._id!,
|
||||
@ -267,7 +295,7 @@ export default class Connection {
|
||||
this._firstFrame = true;
|
||||
}
|
||||
if (vf.vp9s) {
|
||||
let dec = this._videoDecoder;
|
||||
const dec = this._videoDecoder;
|
||||
// dec.sync();
|
||||
vf.vp9s.frames.forEach((f) => {
|
||||
dec.processFrame(f.data.slice(0).buffer, (ok: any) => {
|
||||
@ -278,6 +306,44 @@ export default class Connection {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handlePeerInfo(pi: message.PeerInfo) {
|
||||
this._peerInfo = pi;
|
||||
if (pi.displays.length == 0) {
|
||||
this.msgbox("error", "Remote Error", "No Display");
|
||||
return;
|
||||
}
|
||||
this.msgbox("success", "Successful", "Connected, waiting for image...");
|
||||
globals.pushEvent("peer_info", pi);
|
||||
}
|
||||
|
||||
handleMisc(misc: message.Misc) {
|
||||
if (misc.audioFormat) {
|
||||
//
|
||||
} else if (misc.permissionInfo) {
|
||||
const p = misc.permissionInfo;
|
||||
console.info("Change permission " + p.permission + " -> " + p.enabled);
|
||||
let name;
|
||||
switch (p.permission) {
|
||||
case message.PermissionInfo_Permission.Keyboard:
|
||||
name = "keyboard";
|
||||
break;
|
||||
case message.PermissionInfo_Permission.Clipboard:
|
||||
name = "clipboard";
|
||||
break;
|
||||
case message.PermissionInfo_Permission.Audio:
|
||||
name = "audio";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
globals.pushEvent("permission", { [name]: p.enabled });
|
||||
} else if (misc.switchDisplay) {
|
||||
globals.pushEvent("switch_display", misc.switchDisplay);
|
||||
} else if (misc.closeReason) {
|
||||
this.msgbox("error", "Connection Error", misc.closeReason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
|
@ -1,7 +1,39 @@
|
||||
import Connection from "./connection";
|
||||
import _sodium from "libsodium-wrappers";
|
||||
import { ZSTDecoder } from 'zstddec';
|
||||
|
||||
const decompressor = new ZSTDDecoder();
|
||||
await decompressor.init();
|
||||
|
||||
var currentFrame = undefined;
|
||||
var events = [];
|
||||
|
||||
window.currentConnection = undefined;
|
||||
window.getRgba = () => currentFrame;
|
||||
window.getLanguage = () => navigator.language;
|
||||
|
||||
export function msgbox(type, title, text) {
|
||||
text = text.toLowerCase();
|
||||
var hasRetry = msgtype == "error"
|
||||
&& title == "Connection Error"
|
||||
&& !text.indexOf("offline") >= 0
|
||||
&& !text.indexOf("exist") >= 0
|
||||
&& !text.indexOf("handshake") >= 0
|
||||
&& !text.indexOf("failed") >= 0
|
||||
&& !text.indexOf("resolve") >= 0
|
||||
&& !text.indexOf("mismatch") >= 0
|
||||
&& !text.indexOf("manually") >= 0;
|
||||
events.push({ name: 'msgbox', type, title, text, hasRetry });
|
||||
}
|
||||
|
||||
export function pushEvent(name, payload) {
|
||||
payload.name = name;
|
||||
events.push(payload);
|
||||
}
|
||||
|
||||
export function draw(frame) {
|
||||
currentFrame = frame;
|
||||
}
|
||||
|
||||
export function setConn(conn) {
|
||||
window.currentConnection = conn;
|
||||
@ -14,6 +46,7 @@ export function getConn() {
|
||||
export function close() {
|
||||
getConn()?.close();
|
||||
setConn(undefined);
|
||||
currentFrame = undefined;
|
||||
}
|
||||
|
||||
export function newConn() {
|
||||
@ -73,4 +106,58 @@ export function encrypt(unsigned, nonce, key) {
|
||||
|
||||
export function decrypt(signed, nonce, key) {
|
||||
return sodium.crypto_secretbox_open_easy(signed, makeOnce(nonce), key);
|
||||
}
|
||||
|
||||
export function decompress(compressedArray) {
|
||||
const MAX = 1024 * 1024 * 64;
|
||||
const MIN = 1024 * 1024;
|
||||
let n = 30 * data.length;
|
||||
if (n > MAX) {
|
||||
n = MAX;
|
||||
}
|
||||
if (n < MIN) {
|
||||
n = MIN;
|
||||
}
|
||||
try {
|
||||
return decompressor.decode(compressedArray, n);
|
||||
} catch (e) {
|
||||
console.error('decompress failed: ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
window.setByName = (name, value) => {
|
||||
switch (name) {
|
||||
case 'connect':
|
||||
newConn();
|
||||
break;
|
||||
case 'login':
|
||||
currentConnection.login(value.password, value.remember);
|
||||
break;
|
||||
case 'close':
|
||||
close();
|
||||
break;
|
||||
case 'refresh':
|
||||
currentConnection.refresh();
|
||||
break;
|
||||
case 'reconnect':
|
||||
currentConnection.reconnect();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
window.getByName = (name, value) => {
|
||||
switch (name) {
|
||||
case 'peers':
|
||||
return localStorage.getItem('peers');
|
||||
break;
|
||||
case 'event':
|
||||
if (events.length) {
|
||||
const e = events[0];
|
||||
events.splice(0, 1);
|
||||
return e;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
@ -376,3 +376,8 @@ vite@^2.7.2:
|
||||
rollup "^2.59.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
zstddec@^0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/zstddec/-/zstddec-0.0.2.tgz#57e2f28dd1ff56b750e07d158a43f0611ad9eeb4"
|
||||
integrity sha512-DCo0oxvcvOTGP/f5FA6tz2Z6wF+FIcEApSTu0zV5sQgn9hoT5lZ9YRAKUraxt9oP7l4e8TnNdi8IZTCX6WCkwA==
|
||||
|
Loading…
Reference in New Issue
Block a user