Compare commits
3 commits
115a78be01
...
7a2c81886c
Author | SHA1 | Date | |
---|---|---|---|
Lily Tsuru | 7a2c81886c | ||
Lily Tsuru | 4212050ae5 | ||
Lily Tsuru | 7b9c71d534 |
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
||||||
Copyright 2023 Lily Tsuru/modeco80 <lily.modeco80@protonmail.ch>
|
Copyright 2023-2024 Lily Tsuru/modeco80 <lily.modeco80@protonmail.ch>
|
||||||
Please see qemu/src/rfb/LICENSE for additional terms.
|
Please see qemu/src/rfb/LICENSE for additional terms.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
|
|
@ -3,15 +3,25 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"description": "socket 2.0 backend",
|
"description": "socket 2.0 backend",
|
||||||
|
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc"
|
"build": "parcel build src/index.ts --target node"
|
||||||
},
|
},
|
||||||
|
|
||||||
"author": "modeco80",
|
"author": "modeco80",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
||||||
|
"targets": {
|
||||||
|
"node":{
|
||||||
|
"context": "node",
|
||||||
|
"outputFormat": "esmodule"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/websocket": "^10.0.1",
|
"@fastify/websocket": "^10.0.1",
|
||||||
"@julusian/jpeg-turbo": "^2.1.0",
|
|
||||||
"@socketcomputer/qemu": "*",
|
"@socketcomputer/qemu": "*",
|
||||||
"@socketcomputer/shared": "*",
|
"@socketcomputer/shared": "*",
|
||||||
"fastify": "^4.26.2",
|
"fastify": "^4.26.2",
|
||||||
|
@ -19,6 +29,7 @@
|
||||||
"canvas": "^2.11.2"
|
"canvas": "^2.11.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"parcel": "^2.12.0",
|
||||||
"@types/ws": "^8.5.10"
|
"@types/ws": "^8.5.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ export function Slot_PCDef(
|
||||||
pushOption('-device usb-tablet');
|
pushOption('-device usb-tablet');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: "socketvm1",
|
id: "socketvm2-test",
|
||||||
command: qCommand
|
command: qCommand
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { QemuVmDefinition, QemuDisplay, QemuVM, VMState, setSnapshot, GenMacAddress } from '@socketcomputer/qemu';
|
import { QemuVmDefinition, QemuDisplay, QemuVM, VMState, setSnapshot } from '@socketcomputer/qemu';
|
||||||
import { Slot_PCDef } from './SlotQemuDefs.js';
|
import { Slot_PCDef } from './SlotQemuDefs.js';
|
||||||
import { ExtendableTimer } from './ExtendableTimer.js';
|
import { ExtendableTimer } from './ExtendableTimer.js';
|
||||||
import { EventEmitter } from 'node:events';
|
import { EventEmitter } from 'node:events';
|
||||||
|
@ -20,7 +20,7 @@ const kCanvasJpegQuality = 0.25;
|
||||||
class VMUser {
|
class VMUser {
|
||||||
public connection: WebSocket;
|
public connection: WebSocket;
|
||||||
public address: string;
|
public address: string;
|
||||||
public username: string;
|
public username: string = "";
|
||||||
private vm: SocketVM;
|
private vm: SocketVM;
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,10 +49,10 @@ class VMUser {
|
||||||
async SendBuffer(buffer: ArrayBuffer): Promise<void> {
|
async SendBuffer(buffer: ArrayBuffer): Promise<void> {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
if (this.connection.readyState !== WebSocket.CLOSED) {
|
if (this.connection.readyState !== WebSocket.CLOSED) {
|
||||||
this.connection.send(buffer, (err) => {
|
this.connection.send(buffer);
|
||||||
res();
|
res();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
rej(new Error('connection haves closed'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,14 +73,17 @@ type userAndTime = {
|
||||||
class TurnQueue extends EventEmitter {
|
class TurnQueue extends EventEmitter {
|
||||||
private queue: Queue<VMUser> = new Queue<VMUser>();
|
private queue: Queue<VMUser> = new Queue<VMUser>();
|
||||||
private turnTime = kTurnTimeSeconds;
|
private turnTime = kTurnTimeSeconds;
|
||||||
private interval: NodeJS.Timeout = null;
|
private interval: NodeJS.Timeout|null = null;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CurrentUser(): VMUser {
|
public CurrentUser(): VMUser|null {
|
||||||
return this.queue.peek();
|
if(this.queue.peek() == undefined)
|
||||||
|
return null;
|
||||||
|
// We already check if it'll be undefined
|
||||||
|
return this.queue.peek()!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TryEnqueue(user: VMUser) {
|
public TryEnqueue(user: VMUser) {
|
||||||
|
@ -132,7 +135,7 @@ class TurnQueue extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private nextTurn() {
|
private nextTurn() {
|
||||||
clearInterval(this.interval);
|
clearInterval(this.interval!);
|
||||||
if (this.queue.size === 0) {
|
if (this.queue.size === 0) {
|
||||||
} else {
|
} else {
|
||||||
this.turnTime = kTurnTimeSeconds;
|
this.turnTime = kTurnTimeSeconds;
|
||||||
|
@ -145,26 +148,24 @@ class TurnQueue extends EventEmitter {
|
||||||
|
|
||||||
class SocketVM extends EventEmitter {
|
class SocketVM extends EventEmitter {
|
||||||
private vm: QemuVM;
|
private vm: QemuVM;
|
||||||
private display: QemuDisplay;
|
private display: QemuDisplay|null = null;
|
||||||
|
|
||||||
private timer: ExtendableTimer = null;
|
private timer: ExtendableTimer = new ExtendableTimer(15);
|
||||||
private users: Array<VMUser> = [];
|
private users: Array<VMUser> = [];
|
||||||
private queue: TurnQueue = new TurnQueue();
|
private queue: TurnQueue = new TurnQueue();
|
||||||
|
|
||||||
constructor(vm: QemuVM) {
|
constructor(vm: QemuVM) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.vm = vm;
|
this.vm = vm;
|
||||||
this.timer = new ExtendableTimer(15);
|
|
||||||
|
|
||||||
this.timer.on('expired', async () => {
|
this.timer.on('expired', async () => {
|
||||||
// bye bye!
|
// bye bye!
|
||||||
console.log(`[SocketVM] VM expired, resetting..`);
|
console.log(`[SocketVM] VM timer expired, resetting..`);
|
||||||
await this.vm.Stop();
|
await this.vm.Stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.timer.on('expiry-near', async () => {
|
this.timer.on('expiry-near', async () => {
|
||||||
console.log(`[SocketVM] about to expire!`);
|
console.log(`[SocketVM] VM timer expires in 1 minute.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.queue.on('turnQueue', (arr: Array<userAndTime>) => {
|
this.queue.on('turnQueue', (arr: Array<userAndTime>) => {
|
||||||
|
@ -296,14 +297,12 @@ class SocketVM extends EventEmitter {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Shared.MessageType.Key:
|
case Shared.MessageType.Key:
|
||||||
console.log("GOT key event", (message as Shared.KeyMessage).keysym, (message as Shared.KeyMessage).pressed)
|
|
||||||
if(user != this.queue.CurrentUser())
|
if(user != this.queue.CurrentUser())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(this.display == null)
|
if(this.display == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
console.log("valid key event", (message as Shared.KeyMessage).keysym, (message as Shared.KeyMessage).pressed);
|
|
||||||
this.display.KeyboardEvent((message as Shared.KeyMessage).keysym, (message as Shared.KeyMessage).pressed);
|
this.display.KeyboardEvent((message as Shared.KeyMessage).keysym, (message as Shared.KeyMessage).pressed);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -329,7 +328,7 @@ class SocketVM extends EventEmitter {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|
||||||
// Hook up the display
|
// Hook up the display
|
||||||
this.display.on('resize', async (width, height) => {
|
this.display?.on('resize', async (width: number, height: number) => {
|
||||||
if(self.display == null)
|
if(self.display == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -353,7 +352,7 @@ class SocketVM extends EventEmitter {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.display.on('rect', async (x, y, rect: ImageData) => {
|
this.display?.on('rect', async (x: number, y: number, rect: ImageData) => {
|
||||||
let canvas = new Canvas(rect.width, rect.height);
|
let canvas = new Canvas(rect.width, rect.height);
|
||||||
canvas.getContext('2d').putImageData(rect, 0, 0);
|
canvas.getContext('2d').putImageData(rect, 0, 0);
|
||||||
|
|
||||||
|
@ -376,7 +375,7 @@ class SocketVM extends EventEmitter {
|
||||||
|
|
||||||
await user.SendMessage((encoder: Shared.MessageEncoder) => {
|
await user.SendMessage((encoder: Shared.MessageEncoder) => {
|
||||||
encoder.Init(8);
|
encoder.Init(8);
|
||||||
encoder.SetDisplaySizeMessage(this.display.Size().width, this.display.Size().height);
|
encoder.SetDisplaySizeMessage(this.display!.Size().width, this.display!.Size().height);
|
||||||
return encoder.Finish();
|
return encoder.Finish();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -392,8 +391,21 @@ class SocketVM extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CONFIG types (not used yet)
|
||||||
|
export type SocketComputerConfig_VM = {
|
||||||
|
ramsize: string,
|
||||||
|
hda: string,
|
||||||
|
netdev: string
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SocketComputerConfig = {
|
||||||
|
listen: string,
|
||||||
|
port: number
|
||||||
|
vm: SocketComputerConfig_VM
|
||||||
|
};
|
||||||
|
|
||||||
export class SocketComputerServer {
|
export class SocketComputerServer {
|
||||||
private vm: SocketVM = null;
|
private vm: SocketVM|null = null;
|
||||||
private fastify: FastifyInstance = fastify({
|
private fastify: FastifyInstance = fastify({
|
||||||
exposeHeadRoutes: false
|
exposeHeadRoutes: false
|
||||||
});
|
});
|
||||||
|
@ -433,12 +445,13 @@ export class SocketComputerServer {
|
||||||
CTRoutes(app: FastifyInstance) {
|
CTRoutes(app: FastifyInstance) {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|
||||||
|
// @ts-ignore (fastify types are broken...)
|
||||||
app.get('/', { websocket: true }, (connection: fastifyWebsocket.WebSocket, req: FastifyRequest) => {
|
app.get('/', { websocket: true }, (connection: fastifyWebsocket.WebSocket, req: FastifyRequest) => {
|
||||||
let address = req.ip;
|
let address = req.ip;
|
||||||
if(req.headers["cf-connecting-ip"] !== undefined) {
|
if(req.headers["cf-connecting-ip"] !== undefined) {
|
||||||
address = req.headers["cf-connecting-ip"] as string;
|
address = req.headers["cf-connecting-ip"] as string;
|
||||||
}
|
}
|
||||||
new VMUser(connection, self.vm, address);
|
new VMUser(connection, self.vm!, address);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
package.json
10
package.json
|
@ -8,15 +8,21 @@
|
||||||
"webapp"
|
"webapp"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:frontend": "npm -w shared run build && npm -w webapp run build",
|
"build": "yarn build:service && yarn build:frontend",
|
||||||
"build:service": "npm -w shared run build && npm -w qemu run build && npm -w backend run build"
|
"build:service": "npm -w shared run build && npm -w qemu run build && npm -w backend run build",
|
||||||
|
"build:frontend": "npm -w shared run build && npm -w webapp run build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"canvas": "^2.11.2"
|
"canvas": "^2.11.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"parcel": "^2.12.0",
|
||||||
|
"@parcel/packager-ts": "2.12.0",
|
||||||
|
"@parcel/transformer-sass": "^2.12.0",
|
||||||
|
"@parcel/transformer-typescript-types": "2.12.0",
|
||||||
"@types/node": "^20.12.2",
|
"@types/node": "^20.12.2",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
|
"stream-http": "^3.1.0",
|
||||||
"typescript": "^5.4.3"
|
"typescript": "^5.4.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,30 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"description": "QEMU runtime for socketcomputer backend",
|
"description": "QEMU runtime for socketcomputer backend",
|
||||||
"main": "dist/src/index.js",
|
"exports": "./dist/index.js",
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc"
|
"build": "parcel build src/index.ts --target node --target types"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"targets": {
|
||||||
|
"types": {},
|
||||||
|
"node": {
|
||||||
|
"context": "node",
|
||||||
|
"isLibrary": true,
|
||||||
|
"outputFormat": "esmodule"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
||||||
"canvas": "^2.11.2",
|
"canvas": "^2.11.2",
|
||||||
"execa": "^8.0.1",
|
"execa": "^8.0.1",
|
||||||
"split": "^1.0.1"
|
"split": "^1.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"parcel": "^2.12.0",
|
||||||
|
"@types/node": "^20.12.2",
|
||||||
|
"@types/split": "^1.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,11 +138,11 @@ export class QemuDisplay extends EventEmitter {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseEvent(x, y, buttons) {
|
MouseEvent(x: number, y: number, buttons: number) {
|
||||||
this.displayVnc.sendPointerEvent(x, y, buttons);
|
this.displayVnc.sendPointerEvent(x, y, buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyboardEvent(keysym, pressed) {
|
KeyboardEvent(keysym: number, pressed: boolean) {
|
||||||
this.displayVnc.sendKeyEvent(keysym, pressed);
|
this.displayVnc.sendKeyEvent(keysym, pressed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ const kMaxFailCount = 5;
|
||||||
|
|
||||||
let gVMShouldSnapshot = false;
|
let gVMShouldSnapshot = false;
|
||||||
|
|
||||||
async function Sleep(ms) {
|
async function Sleep(ms: number) {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ export class QemuVM extends EventEmitter {
|
||||||
if (this.state !== stateShouldBe) throw new Error(message);
|
if (this.state !== stateShouldBe) throw new Error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SetState(state) {
|
private SetState(state: VMState) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.emit('statechange', this.state);
|
this.emit('statechange', this.state);
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ export class QemuVM extends EventEmitter {
|
||||||
return `${kVmTmpPathBase}/socket2-${this.definition.id}-vnc`;
|
return `${kVmTmpPathBase}/socket2-${this.definition.id}-vnc`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async StartQemu(split) {
|
private async StartQemu(split: Array<string>) {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|
||||||
this.SetState(VMState.Starting);
|
this.SetState(VMState.Starting);
|
||||||
|
@ -227,11 +227,11 @@ export class QemuVM extends EventEmitter {
|
||||||
switch (ev.event) {
|
switch (ev.event) {
|
||||||
// Handle the STOP event sent when using -no-shutdown
|
// Handle the STOP event sent when using -no-shutdown
|
||||||
case 'STOP':
|
case 'STOP':
|
||||||
await self.qmpInstance.Execute('system_reset');
|
await self.qmpInstance?.Execute('system_reset');
|
||||||
break;
|
break;
|
||||||
case 'RESET':
|
case 'RESET':
|
||||||
self.VMLog('got a reset event!');
|
self.VMLog('got a reset event!');
|
||||||
await self.qmpInstance.Execute('cont');
|
await self.qmpInstance?.Execute('cont');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -250,7 +250,7 @@ export class QemuVM extends EventEmitter {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Sleep(500);
|
await Sleep(500);
|
||||||
this.qmpInstance.ConnectUNIX(this.GetQmpPath());
|
this.qmpInstance?.ConnectUNIX(this.GetQmpPath());
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// just try again
|
// just try again
|
||||||
await Sleep(500);
|
await Sleep(500);
|
||||||
|
@ -261,7 +261,7 @@ export class QemuVM extends EventEmitter {
|
||||||
|
|
||||||
private async DisconnectDisplay() {
|
private async DisconnectDisplay() {
|
||||||
try {
|
try {
|
||||||
this.display.Disconnect();
|
this.display?.Disconnect();
|
||||||
this.display = null; // disassociate with that display object.
|
this.display = null; // disassociate with that display object.
|
||||||
|
|
||||||
await unlink(this.GetVncPath());
|
await unlink(this.GetVncPath());
|
||||||
|
|
|
@ -123,7 +123,7 @@ export default class QmpClient extends Socket {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Connect(host, port) {
|
Connect(host: string, port: number) {
|
||||||
super.connect(port, host);
|
super.connect(port, host);
|
||||||
this.ConnectImpl();
|
this.ConnectImpl();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Copyright 2021 Filipe Calaça Barbosa
|
Copyright 2021 Filipe Calaça Barbosa
|
||||||
Copyright 2022 dither
|
Copyright 2022 dither
|
||||||
Copyright 2023 Lily Tsuru/modeco80 <lily.modeco80@protonmail.ch>
|
Copyright 2023-2024 Lily Tsuru/modeco80 <lily.modeco80@protonmail.ch>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
|
|
||||||
The source here was originally taken from a fork of [vnc-rfb-client](https://github.com/ayunami2000/vnc-rfb-client) made for the LucidVM project, available [here](https://github.com/lucidvm/rfb).
|
The source here was originally taken from a fork of [vnc-rfb-client](https://github.com/ayunami2000/vnc-rfb-client) made for the LucidVM project, available [here](https://github.com/lucidvm/rfb).
|
||||||
|
|
||||||
It has been grossly modified for the usecases for the `@socketcomputer/qemu` package:
|
It has been grossly modified for the usecases for the socket2 backend, but is more than likely usable to other clients.
|
||||||
|
|
||||||
- converted to TypeScript
|
- converted to (strict) TypeScript; my initial port beforehand was not strict and it Sucked
|
||||||
|
- Also, actually use interfaces, and reduce the amount of code duplicated significantly in the rect decoders.
|
||||||
- all modules rewritten to use ESM
|
- all modules rewritten to use ESM
|
||||||
- some noisy debug prints removed
|
- some noisy debug prints removed
|
||||||
- (some, very tiny) code cleanup
|
- (some, very tiny) code cleanup
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
|
||||||
|
import { IRectDecoder } from './decoders/decoder.js';
|
||||||
import { HextileDecoder } from './decoders/hextile.js';
|
import { HextileDecoder } from './decoders/hextile.js';
|
||||||
import { RawDecoder } from './decoders/raw.js';
|
import { RawDecoder } from './decoders/raw.js';
|
||||||
import { ZrleDecoder } from './decoders/zrle.js';
|
import { ZrleDecoder } from './decoders/zrle.js';
|
||||||
|
@ -13,57 +15,79 @@ import * as crypto from 'node:crypto';
|
||||||
|
|
||||||
import { SocketBuffer } from './socketbuffer.js';
|
import { SocketBuffer } from './socketbuffer.js';
|
||||||
|
|
||||||
|
import { VncRectangle, Color3, PixelFormat, Cursor } from './types.js';
|
||||||
|
|
||||||
export class VncClient extends EventEmitter {
|
export class VncClient extends EventEmitter {
|
||||||
// These are in no particular order.
|
// These are in no particular order.
|
||||||
|
|
||||||
public debug: Boolean;
|
public debug: boolean = false;
|
||||||
|
|
||||||
private _connected: Boolean;
|
private _connected: boolean = false;
|
||||||
private _authenticated: Boolean;
|
private _authenticated: boolean = false;
|
||||||
private _version: string;
|
private _version: string = "";
|
||||||
private _password: string;
|
private _password: string = "";
|
||||||
|
|
||||||
private _audioChannels: number;
|
private _audioChannels: number = 2;
|
||||||
private _audioFrequency: number;
|
private _audioFrequency: number = 22050;
|
||||||
|
|
||||||
private _rects: number;
|
private _rects: number = 0;
|
||||||
|
|
||||||
private _decoders: any; // no real good way to type this yet. will do it later
|
private _decoders: Array<IRectDecoder> = [];
|
||||||
|
|
||||||
private _fps: number;
|
private _fps: number;
|
||||||
private _timerInterval: number;
|
private _timerInterval: number;
|
||||||
private _timerPointer;
|
private _timerPointer : NodeJS.Timeout|null = null;
|
||||||
|
|
||||||
public fb: Buffer;
|
public fb: Buffer = Buffer.from([]);
|
||||||
|
|
||||||
private _handshaked: Boolean;
|
private _handshaked: boolean = false;
|
||||||
private _waitingServerInit: Boolean;
|
private _waitingServerInit: boolean = false;
|
||||||
private _expectingChallenge: Boolean;
|
private _expectingChallenge: boolean = false;
|
||||||
private _challengeResponseSent: Boolean;
|
private _challengeResponseSent: boolean = false;
|
||||||
|
|
||||||
private _set8BitColor: Boolean;
|
private _set8BitColor: boolean = false;
|
||||||
private _frameBufferReady = false;
|
private _frameBufferReady = false;
|
||||||
private _firstFrameReceived = false;
|
private _firstFrameReceived = false;
|
||||||
private _processingFrame = false;
|
private _processingFrame = false;
|
||||||
|
|
||||||
private _relativePointer: Boolean;
|
private _relativePointer: boolean = false;
|
||||||
|
|
||||||
public bigEndianFlag: Boolean;
|
public bigEndianFlag: boolean = false;
|
||||||
|
|
||||||
public clientWidth: number;
|
public clientWidth: number = 0;
|
||||||
public clientHeight: number;
|
public clientHeight: number = 0;
|
||||||
public clientName: string;
|
public clientName: string = "";
|
||||||
|
|
||||||
public pixelFormat: any;
|
public pixelFormat: PixelFormat = {
|
||||||
|
bitsPerPixel: 0,
|
||||||
|
depth: 0,
|
||||||
|
bigEndianFlag: 0,
|
||||||
|
trueColorFlag: 0,
|
||||||
|
redMax: 0,
|
||||||
|
greenMax: 0,
|
||||||
|
blueMax: 0,
|
||||||
|
redShift: 0,
|
||||||
|
greenShift: 0,
|
||||||
|
blueShift: 0
|
||||||
|
};
|
||||||
|
|
||||||
private _colorMap: any[];
|
private _colorMap: Color3[] = [];
|
||||||
private _audioData: Buffer;
|
private _audioData: Buffer = Buffer.from([]);
|
||||||
|
|
||||||
private _cursor: any;
|
private _cursor: Cursor = {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
cursorPixels: null,
|
||||||
|
bitmask: null,
|
||||||
|
posX: 0,
|
||||||
|
posY: 0
|
||||||
|
};
|
||||||
|
|
||||||
public encodings: number[];
|
public encodings: number[];
|
||||||
|
|
||||||
private _connection: net.Socket;
|
private _connection: net.Socket|null = null;
|
||||||
private _socketBuffer: SocketBuffer;
|
private _socketBuffer: SocketBuffer;
|
||||||
|
|
||||||
static get consts() {
|
static get consts() {
|
||||||
|
@ -101,7 +125,7 @@ export class VncClient extends EventEmitter {
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
get localPort() {
|
get localPort() {
|
||||||
return this._connection ? this._connection.localPort : 0;
|
return this._connection ? this._connection?.localPort : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(options: any = { debug: false, fps: 0, encodings: [] }) {
|
constructor(options: any = { debug: false, fps: 0, encodings: [] }) {
|
||||||
|
@ -125,7 +149,7 @@ export class VncClient extends EventEmitter {
|
||||||
this._audioFrequency = options.audioFrequency || 22050;
|
this._audioFrequency = options.audioFrequency || 22050;
|
||||||
|
|
||||||
this._rects = 0;
|
this._rects = 0;
|
||||||
this._decoders = {};
|
|
||||||
this._decoders[consts.encodings.raw] = new RawDecoder();
|
this._decoders[consts.encodings.raw] = new RawDecoder();
|
||||||
// TODO: Implement tight encoding
|
// TODO: Implement tight encoding
|
||||||
// this._decoders[encodings.tight] = new tightDecoder();
|
// this._decoders[encodings.tight] = new tightDecoder();
|
||||||
|
@ -155,7 +179,7 @@ export class VncClient extends EventEmitter {
|
||||||
* Adjuste the configured FPS
|
* Adjuste the configured FPS
|
||||||
* @param fps {number} - Number of update requests send by second
|
* @param fps {number} - Number of update requests send by second
|
||||||
*/
|
*/
|
||||||
changeFps(fps) {
|
changeFps(fps: number) {
|
||||||
if (!Number.isNaN(fps)) {
|
if (!Number.isNaN(fps)) {
|
||||||
this._fps = Number(fps);
|
this._fps = Number(fps);
|
||||||
this._timerInterval = this._fps > 0 ? 1000 / this._fps : 0;
|
this._timerInterval = this._fps > 0 ? 1000 / this._fps : 0;
|
||||||
|
@ -178,7 +202,7 @@ export class VncClient extends EventEmitter {
|
||||||
* @param options
|
* @param options
|
||||||
*/
|
*/
|
||||||
connect(
|
connect(
|
||||||
options /* = {
|
options: any /* = {
|
||||||
host: '',
|
host: '',
|
||||||
password: '',
|
password: '',
|
||||||
path: '',
|
path: '',
|
||||||
|
@ -199,31 +223,31 @@ export class VncClient extends EventEmitter {
|
||||||
this._connection = net.connect(options.port || 5900, options.host);
|
this._connection = net.connect(options.port || 5900, options.host);
|
||||||
|
|
||||||
// disable nagle's algorithm for TCP
|
// disable nagle's algorithm for TCP
|
||||||
this._connection.setNoDelay();
|
this._connection?.setNoDelay();
|
||||||
} else {
|
} else {
|
||||||
// unix socket. bodged in but oh well
|
// unix socket. bodged in but oh well
|
||||||
this._connection = net.connect(options.path);
|
this._connection = net.connect(options.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._connection.on('connect', () => {
|
this._connection?.on('connect', () => {
|
||||||
this._connected = true;
|
this._connected = true;
|
||||||
this.emit('connected');
|
this.emit('connected');
|
||||||
});
|
});
|
||||||
|
|
||||||
this._connection.on('close', () => {
|
this._connection?.on('close', () => {
|
||||||
this.resetState();
|
this.resetState();
|
||||||
this.emit('closed');
|
this.emit('closed');
|
||||||
});
|
});
|
||||||
|
|
||||||
this._connection.on('timeout', () => {
|
this._connection?.on('timeout', () => {
|
||||||
this.emit('connectTimeout');
|
this.emit('connectTimeout');
|
||||||
});
|
});
|
||||||
|
|
||||||
this._connection.on('error', (err) => {
|
this._connection?.on('error', (err) => {
|
||||||
this.emit('connectError', err);
|
this.emit('connectError', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
this._connection.on('data', async (data) => {
|
this._connection?.on('data', async (data) => {
|
||||||
this._socketBuffer.pushData(data);
|
this._socketBuffer.pushData(data);
|
||||||
|
|
||||||
if (!this._handshaked) {
|
if (!this._handshaked) {
|
||||||
|
@ -243,7 +267,7 @@ export class VncClient extends EventEmitter {
|
||||||
*/
|
*/
|
||||||
disconnect() {
|
disconnect() {
|
||||||
if (this._connection) {
|
if (this._connection) {
|
||||||
this._connection.end();
|
this._connection?.end();
|
||||||
this.resetState();
|
this.resetState();
|
||||||
this.emit('disconnected');
|
this.emit('disconnected');
|
||||||
}
|
}
|
||||||
|
@ -269,7 +293,7 @@ export class VncClient extends EventEmitter {
|
||||||
message.writeUInt16BE(width, 6); // Width
|
message.writeUInt16BE(width, 6); // Width
|
||||||
message.writeUInt16BE(height, 8); // Height
|
message.writeUInt16BE(height, 8); // Height
|
||||||
|
|
||||||
this._connection.write(message);
|
this._connection?.write(message);
|
||||||
|
|
||||||
this._frameBufferReady = true;
|
this._frameBufferReady = true;
|
||||||
}
|
}
|
||||||
|
@ -283,15 +307,15 @@ export class VncClient extends EventEmitter {
|
||||||
// Handshake, negotiating protocol version
|
// Handshake, negotiating protocol version
|
||||||
if (this._socketBuffer.toString() === consts.versionString.V3_003) {
|
if (this._socketBuffer.toString() === consts.versionString.V3_003) {
|
||||||
this._log('Sending 3.3', true);
|
this._log('Sending 3.3', true);
|
||||||
this._connection.write(consts.versionString.V3_003);
|
this._connection?.write(consts.versionString.V3_003);
|
||||||
this._version = '3.3';
|
this._version = '3.3';
|
||||||
} else if (this._socketBuffer.toString() === consts.versionString.V3_007) {
|
} else if (this._socketBuffer.toString() === consts.versionString.V3_007) {
|
||||||
this._log('Sending 3.7', true);
|
this._log('Sending 3.7', true);
|
||||||
this._connection.write(consts.versionString.V3_007);
|
this._connection?.write(consts.versionString.V3_007);
|
||||||
this._version = '3.7';
|
this._version = '3.7';
|
||||||
} else if (this._socketBuffer.toString() === consts.versionString.V3_008) {
|
} else if (this._socketBuffer.toString() === consts.versionString.V3_008) {
|
||||||
this._log('Sending 3.8', true);
|
this._log('Sending 3.8', true);
|
||||||
this._connection.write(consts.versionString.V3_008);
|
this._connection?.write(consts.versionString.V3_008);
|
||||||
this._version = '3.8';
|
this._version = '3.8';
|
||||||
} else {
|
} else {
|
||||||
// Negotiating auth mechanism
|
// Negotiating auth mechanism
|
||||||
|
@ -299,10 +323,10 @@ export class VncClient extends EventEmitter {
|
||||||
if (this._socketBuffer.includes(0x02) && this._password) {
|
if (this._socketBuffer.includes(0x02) && this._password) {
|
||||||
this._log('Password provided and server support VNC auth. Choosing VNC auth.', true);
|
this._log('Password provided and server support VNC auth. Choosing VNC auth.', true);
|
||||||
this._expectingChallenge = true;
|
this._expectingChallenge = true;
|
||||||
this._connection.write(Buffer.from([0x02]));
|
this._connection?.write(Buffer.from([0x02]));
|
||||||
} else if (this._socketBuffer.includes(1)) {
|
} else if (this._socketBuffer.includes(1)) {
|
||||||
this._log('Password not provided or server does not support VNC auth. Trying none.', true);
|
this._log('Password not provided or server does not support VNC auth. Trying none.', true);
|
||||||
this._connection.write(Buffer.from([0x01]));
|
this._connection?.write(Buffer.from([0x01]));
|
||||||
if (this._version === '3.7') {
|
if (this._version === '3.7') {
|
||||||
this._waitingServerInit = true;
|
this._waitingServerInit = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -352,7 +376,7 @@ export class VncClient extends EventEmitter {
|
||||||
response.fill(des1.update(this._socketBuffer.buffer.slice(0, 8)), 0, 8);
|
response.fill(des1.update(this._socketBuffer.buffer.slice(0, 8)), 0, 8);
|
||||||
response.fill(des2.update(this._socketBuffer.buffer.slice(8, 16)), 8, 16);
|
response.fill(des2.update(this._socketBuffer.buffer.slice(8, 16)), 8, 16);
|
||||||
|
|
||||||
this._connection.write(response);
|
this._connection?.write(response);
|
||||||
this._challengeResponseSent = true;
|
this._challengeResponseSent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,7 +387,7 @@ export class VncClient extends EventEmitter {
|
||||||
* Reverse bits order of a byte
|
* Reverse bits order of a byte
|
||||||
* @param buf - Buffer to be flipped
|
* @param buf - Buffer to be flipped
|
||||||
*/
|
*/
|
||||||
reverseBits(buf) {
|
reverseBits(buf: Buffer) {
|
||||||
for (let x = 0; x < buf.length; x++) {
|
for (let x = 0; x < buf.length; x++) {
|
||||||
let newByte = 0;
|
let newByte = 0;
|
||||||
newByte += buf[x] & 128 ? 1 : 0;
|
newByte += buf[x] & 128 ? 1 : 0;
|
||||||
|
@ -390,6 +414,7 @@ export class VncClient extends EventEmitter {
|
||||||
|
|
||||||
this.clientWidth = this._socketBuffer.readUInt16BE();
|
this.clientWidth = this._socketBuffer.readUInt16BE();
|
||||||
this.clientHeight = this._socketBuffer.readUInt16BE();
|
this.clientHeight = this._socketBuffer.readUInt16BE();
|
||||||
|
|
||||||
this.pixelFormat.bitsPerPixel = this._socketBuffer.readUInt8();
|
this.pixelFormat.bitsPerPixel = this._socketBuffer.readUInt8();
|
||||||
this.pixelFormat.depth = this._socketBuffer.readUInt8();
|
this.pixelFormat.depth = this._socketBuffer.readUInt8();
|
||||||
this.pixelFormat.bigEndianFlag = this._socketBuffer.readUInt8();
|
this.pixelFormat.bigEndianFlag = this._socketBuffer.readUInt8();
|
||||||
|
@ -457,7 +482,7 @@ export class VncClient extends EventEmitter {
|
||||||
message.writeUInt8(0, 19); // PixelFormat - Padding
|
message.writeUInt8(0, 19); // PixelFormat - Padding
|
||||||
|
|
||||||
// Envia um setPixelFormat trocando para mapa de cores
|
// Envia um setPixelFormat trocando para mapa de cores
|
||||||
this._connection.write(message);
|
this._connection?.write(message);
|
||||||
|
|
||||||
this.pixelFormat.bitsPerPixel = 8;
|
this.pixelFormat.bitsPerPixel = 8;
|
||||||
this.pixelFormat.depth = 8;
|
this.pixelFormat.depth = 8;
|
||||||
|
@ -487,7 +512,7 @@ export class VncClient extends EventEmitter {
|
||||||
message.writeInt32BE(consts.encodings.raw, offset + 4);
|
message.writeInt32BE(consts.encodings.raw, offset + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._connection.write(message);
|
this._connection?.write(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -498,7 +523,7 @@ export class VncClient extends EventEmitter {
|
||||||
//this._log(`Sending clientInit`);
|
//this._log(`Sending clientInit`);
|
||||||
this._waitingServerInit = true;
|
this._waitingServerInit = true;
|
||||||
// Shared bit set
|
// Shared bit set
|
||||||
this._connection.write('1');
|
this._connection?.write('1');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -558,6 +583,10 @@ export class VncClient extends EventEmitter {
|
||||||
data: Buffer.alloc(4)
|
data: Buffer.alloc(4)
|
||||||
};
|
};
|
||||||
const { width, height, bitmask, cursorPixels } = this._cursor;
|
const { width, height, bitmask, cursorPixels } = this._cursor;
|
||||||
|
|
||||||
|
if(bitmask == null || cursorPixels == null)
|
||||||
|
throw new Error('No cursor data to get!');
|
||||||
|
|
||||||
const data = Buffer.alloc(height * width * 4);
|
const data = Buffer.alloc(height * width * 4);
|
||||||
for (var y = 0; y < height; y++) {
|
for (var y = 0; y < height; y++) {
|
||||||
for (var x = 0; x < width; x++) {
|
for (var x = 0; x < width; x++) {
|
||||||
|
@ -568,6 +597,7 @@ export class VncClient extends EventEmitter {
|
||||||
case 8:
|
case 8:
|
||||||
console.log(8);
|
console.log(8);
|
||||||
const index = cursorPixels.readUInt8(offset);
|
const index = cursorPixels.readUInt8(offset);
|
||||||
|
// @ts-ignore (This line is extremely suspect anyways. I bet this is horribly broken!!)
|
||||||
const color = this._colorMap[index] | 0xff;
|
const color = this._colorMap[index] | 0xff;
|
||||||
data.writeIntBE(color, offset, 4);
|
data.writeIntBE(color, offset, 4);
|
||||||
break;
|
break;
|
||||||
|
@ -606,12 +636,14 @@ export class VncClient extends EventEmitter {
|
||||||
|
|
||||||
while (this._rects) {
|
while (this._rects) {
|
||||||
await this._socketBuffer.waitBytes(12);
|
await this._socketBuffer.waitBytes(12);
|
||||||
const rect: any = {};
|
const rect: VncRectangle = {
|
||||||
rect.x = this._socketBuffer.readUInt16BE();
|
x: this._socketBuffer.readUInt16BE(),
|
||||||
rect.y = this._socketBuffer.readUInt16BE();
|
y: this._socketBuffer.readUInt16BE(),
|
||||||
rect.width = this._socketBuffer.readUInt16BE();
|
width: this._socketBuffer.readUInt16BE(),
|
||||||
rect.height = this._socketBuffer.readUInt16BE();
|
height: this._socketBuffer.readUInt16BE(),
|
||||||
rect.encoding = this._socketBuffer.readInt32BE();
|
encoding: this._socketBuffer.readInt32BE(),
|
||||||
|
data: null // for now
|
||||||
|
};
|
||||||
|
|
||||||
if (rect.encoding === consts.encodings.pseudoQemuAudio) {
|
if (rect.encoding === consts.encodings.pseudoQemuAudio) {
|
||||||
this.sendAudio(true);
|
this.sendAudio(true);
|
||||||
|
@ -700,7 +732,7 @@ export class VncClient extends EventEmitter {
|
||||||
this._colorMap[firstColor] = {
|
this._colorMap[firstColor] = {
|
||||||
r: Math.floor((this._socketBuffer.readUInt16BE() / 65535) * 255),
|
r: Math.floor((this._socketBuffer.readUInt16BE() / 65535) * 255),
|
||||||
g: Math.floor((this._socketBuffer.readUInt16BE() / 65535) * 255),
|
g: Math.floor((this._socketBuffer.readUInt16BE() / 65535) * 255),
|
||||||
b: Math.floor((this._socketBuffer.readUInt16BE() / 65535) * 255)
|
b: Math.floor((this._socketBuffer.readUInt16BE() / 65535) * 255),
|
||||||
};
|
};
|
||||||
firstColor++;
|
firstColor++;
|
||||||
}
|
}
|
||||||
|
@ -733,7 +765,7 @@ export class VncClient extends EventEmitter {
|
||||||
*/
|
*/
|
||||||
resetState() {
|
resetState() {
|
||||||
if (this._connection) {
|
if (this._connection) {
|
||||||
this._connection.end();
|
this._connection?.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._timerPointer) {
|
if (this._timerPointer) {
|
||||||
|
@ -782,7 +814,7 @@ export class VncClient extends EventEmitter {
|
||||||
this._rects = 0;
|
this._rects = 0;
|
||||||
|
|
||||||
this._colorMap = [];
|
this._colorMap = [];
|
||||||
this.fb = null;
|
this.fb = Buffer.from([]);
|
||||||
|
|
||||||
this._socketBuffer?.flush(false);
|
this._socketBuffer?.flush(false);
|
||||||
|
|
||||||
|
@ -792,7 +824,9 @@ export class VncClient extends EventEmitter {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
cursorPixels: null,
|
cursorPixels: null,
|
||||||
bitmask: null
|
bitmask: null,
|
||||||
|
posX: 0,
|
||||||
|
posY: 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,7 +837,7 @@ export class VncClient extends EventEmitter {
|
||||||
* @param key - Key code (keysym) defined by X Window System, check https://wiki.linuxquestions.org/wiki/List_of_keysyms
|
* @param key - Key code (keysym) defined by X Window System, check https://wiki.linuxquestions.org/wiki/List_of_keysyms
|
||||||
* @param down - True if the key is pressed, false if it is not
|
* @param down - True if the key is pressed, false if it is not
|
||||||
*/
|
*/
|
||||||
sendKeyEvent(key, down = false) {
|
sendKeyEvent(key: number, down: boolean = false) {
|
||||||
const message = Buffer.alloc(8);
|
const message = Buffer.alloc(8);
|
||||||
message.writeUInt8(4); // Message type
|
message.writeUInt8(4); // Message type
|
||||||
message.writeUInt8(down ? 1 : 0, 1); // Down flag
|
message.writeUInt8(down ? 1 : 0, 1); // Down flag
|
||||||
|
@ -812,7 +846,7 @@ export class VncClient extends EventEmitter {
|
||||||
|
|
||||||
message.writeUInt32BE(key, 4); // Key code
|
message.writeUInt32BE(key, 4); // Key code
|
||||||
|
|
||||||
this._connection.write(message);
|
this._connection?.write(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -821,7 +855,7 @@ export class VncClient extends EventEmitter {
|
||||||
* @param yPosition - Y Position
|
* @param yPosition - Y Position
|
||||||
* @param mask - Raw RFB button mask
|
* @param mask - Raw RFB button mask
|
||||||
*/
|
*/
|
||||||
sendPointerEvent(xPosition, yPosition, buttonMask) {
|
sendPointerEvent(xPosition: number, yPosition: number, buttonMask: number) {
|
||||||
const message = Buffer.alloc(6);
|
const message = Buffer.alloc(6);
|
||||||
message.writeUInt8(consts.clientMsgTypes.pointerEvent); // Message type
|
message.writeUInt8(consts.clientMsgTypes.pointerEvent); // Message type
|
||||||
message.writeUInt8(buttonMask, 1); // Button Mask
|
message.writeUInt8(buttonMask, 1); // Button Mask
|
||||||
|
@ -832,14 +866,14 @@ export class VncClient extends EventEmitter {
|
||||||
this._cursor.posX = xPosition;
|
this._cursor.posX = xPosition;
|
||||||
this._cursor.posY = yPosition;
|
this._cursor.posY = yPosition;
|
||||||
|
|
||||||
this._connection.write(message);
|
this._connection?.write(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send client cut message to server
|
* Send client cut message to server
|
||||||
* @param text - latin1 encoded
|
* @param text - latin1 encoded
|
||||||
*/
|
*/
|
||||||
clientCutText(text) {
|
clientCutText(text: string) {
|
||||||
const textBuffer = Buffer.from(text, 'latin1');
|
const textBuffer = Buffer.from(text, 'latin1');
|
||||||
const message = Buffer.alloc(8 + textBuffer.length);
|
const message = Buffer.alloc(8 + textBuffer.length);
|
||||||
message.writeUInt8(6); // Message type
|
message.writeUInt8(6); // Message type
|
||||||
|
@ -849,18 +883,18 @@ export class VncClient extends EventEmitter {
|
||||||
message.writeUInt32BE(textBuffer.length, 4); // Padding
|
message.writeUInt32BE(textBuffer.length, 4); // Padding
|
||||||
textBuffer.copy(message, 8);
|
textBuffer.copy(message, 8);
|
||||||
|
|
||||||
this._connection.write(message);
|
this._connection?.write(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendAudio(enable) {
|
sendAudio(enable: boolean) {
|
||||||
const message = Buffer.alloc(4);
|
const message = Buffer.alloc(4);
|
||||||
message.writeUInt8(consts.clientMsgTypes.qemuAudio); // Message type
|
message.writeUInt8(consts.clientMsgTypes.qemuAudio); // Message type
|
||||||
message.writeUInt8(1, 1); // Submessage Type
|
message.writeUInt8(1, 1); // Submessage Type
|
||||||
message.writeUInt16BE(enable ? 0 : 1, 2); // Operation
|
message.writeUInt16BE(enable ? 0 : 1, 2); // Operation
|
||||||
this._connection.write(message);
|
this._connection?.write(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendAudioConfig(channels, frequency) {
|
sendAudioConfig(channels: number, frequency: number) {
|
||||||
const message = Buffer.alloc(10);
|
const message = Buffer.alloc(10);
|
||||||
message.writeUInt8(consts.clientMsgTypes.qemuAudio); // Message type
|
message.writeUInt8(consts.clientMsgTypes.qemuAudio); // Message type
|
||||||
message.writeUInt8(1, 1); // Submessage Type
|
message.writeUInt8(1, 1); // Submessage Type
|
||||||
|
@ -868,7 +902,7 @@ export class VncClient extends EventEmitter {
|
||||||
message.writeUInt8(0 /*U8*/, 4); // Sample Format
|
message.writeUInt8(0 /*U8*/, 4); // Sample Format
|
||||||
message.writeUInt8(channels, 5); // Number of Channels
|
message.writeUInt8(channels, 5); // Number of Channels
|
||||||
message.writeUInt32BE(frequency, 6); // Frequency
|
message.writeUInt32BE(frequency, 6); // Frequency
|
||||||
this._connection.write(message);
|
this._connection?.write(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -877,7 +911,7 @@ export class VncClient extends EventEmitter {
|
||||||
* @param debug
|
* @param debug
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_log(text, debug = false) {
|
_log(text: string, debug = false) {
|
||||||
if (!debug || (debug && this.debug)) {
|
if (!debug || (debug && this.debug)) {
|
||||||
console.log(text);
|
console.log(text);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
export class CopyRectDecoder {
|
import { SocketBuffer } from "../socketbuffer";
|
||||||
getPixelBytePos(x, y, width, height) {
|
import { IRectDecoder } from "./decoder";
|
||||||
return (y * width + x) * 4;
|
import { getPixelBytePos } from "./util";
|
||||||
}
|
|
||||||
|
|
||||||
async decode(rect, fb, bitsPerPixel, colorMap, screenW, screenH, socket, depth): Promise<void> {
|
import { VncRectangle, Color3 } from "../types";
|
||||||
|
|
||||||
|
export class CopyRectDecoder implements IRectDecoder {
|
||||||
|
async decode(rect: VncRectangle, fb: Buffer, bitsPerPixel: number, colorMap: Array<Color3>, screenW: number, screenH: number, socket: SocketBuffer, depth: number): Promise<void> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
await socket.waitBytes(4);
|
await socket.waitBytes(4);
|
||||||
rect.data = socket.readNBytesOffset(4);
|
rect.data = socket.readNBytesOffset(4);
|
||||||
|
@ -13,8 +15,8 @@ export class CopyRectDecoder {
|
||||||
|
|
||||||
for (let h = 0; h < rect.height; h++) {
|
for (let h = 0; h < rect.height; h++) {
|
||||||
for (let w = 0; w < rect.width; w++) {
|
for (let w = 0; w < rect.width; w++) {
|
||||||
const fbOrigBytePosOffset = this.getPixelBytePos(x + w, y + h, screenW, screenH);
|
const fbOrigBytePosOffset = getPixelBytePos(x + w, y + h, screenW, screenH);
|
||||||
const fbBytePosOffset = this.getPixelBytePos(rect.x + w, rect.y + h, screenW, screenH);
|
const fbBytePosOffset = getPixelBytePos(rect.x + w, rect.y + h, screenW, screenH);
|
||||||
|
|
||||||
fb.writeUInt8(fb.readUInt8(fbOrigBytePosOffset), fbBytePosOffset);
|
fb.writeUInt8(fb.readUInt8(fbOrigBytePosOffset), fbBytePosOffset);
|
||||||
fb.writeUInt8(fb.readUInt8(fbOrigBytePosOffset + 1), fbBytePosOffset + 1);
|
fb.writeUInt8(fb.readUInt8(fbOrigBytePosOffset + 1), fbBytePosOffset + 1);
|
||||||
|
|
7
qemu/src/rfb/decoders/decoder.ts
Normal file
7
qemu/src/rfb/decoders/decoder.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { SocketBuffer } from "../socketbuffer";
|
||||||
|
import { Color3, VncRectangle } from "../types";
|
||||||
|
|
||||||
|
|
||||||
|
export interface IRectDecoder {
|
||||||
|
decode(rect: VncRectangle, fb: Buffer, bitsPerPixel: number, colorMap: Array<Color3>, screenW: number, screenH: number, socket: SocketBuffer, depth: number): Promise<void>;
|
||||||
|
}
|
|
@ -1,27 +1,25 @@
|
||||||
export class HextileDecoder {
|
import { SocketBuffer } from "../socketbuffer";
|
||||||
getPixelBytePos(x, y, width, height) {
|
import { IRectDecoder } from "./decoder";
|
||||||
return (y * width + x) * 4;
|
import { applyColor, getPixelBytePos } from "./util";
|
||||||
}
|
|
||||||
|
|
||||||
async decode(rect, fb, bitsPerPixel, colorMap, screenW, screenH, socket, depth): Promise<void> {
|
import { VncRectangle, Color3 } from "../types";
|
||||||
|
|
||||||
|
export class HextileDecoder implements IRectDecoder {
|
||||||
|
|
||||||
|
async decode(rect: VncRectangle, fb: Buffer, bitsPerPixel: number, colorMap: Array<Color3>, screenW: number, screenH: number, socket: SocketBuffer, depth: number): Promise<void> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
const initialOffset = socket.offset;
|
const initialOffset = socket.offset;
|
||||||
let dataSize = 0;
|
let dataSize = 0;
|
||||||
|
|
||||||
let tiles;
|
let lastSubEncoding = 0;
|
||||||
let totalTiles;
|
|
||||||
let tilesX;
|
|
||||||
let tilesY;
|
|
||||||
|
|
||||||
let lastSubEncoding;
|
|
||||||
|
|
||||||
const backgroundColor = { r: 0, g: 0, b: 0, a: 255 };
|
const backgroundColor = { r: 0, g: 0, b: 0, a: 255 };
|
||||||
const foregroundColor = { r: 0, g: 0, b: 0, a: 255 };
|
const foregroundColor = { r: 0, g: 0, b: 0, a: 255 };
|
||||||
|
|
||||||
tilesX = Math.ceil(rect.width / 16);
|
let tilesX = Math.ceil(rect.width / 16);
|
||||||
tilesY = Math.ceil(rect.height / 16);
|
let tilesY = Math.ceil(rect.height / 16);
|
||||||
tiles = tilesX * tilesY;
|
let tiles = tilesX * tilesY;
|
||||||
totalTiles = tiles;
|
let totalTiles = tiles;
|
||||||
|
|
||||||
while (tiles) {
|
while (tiles) {
|
||||||
await socket.waitBytes(1);
|
await socket.waitBytes(1);
|
||||||
|
@ -42,7 +40,7 @@ export class HextileDecoder {
|
||||||
// We need to ignore zeroed tile after a raw tile
|
// We need to ignore zeroed tile after a raw tile
|
||||||
} else {
|
} else {
|
||||||
// If zeroed tile and last tile was not raw, use the last backgroundColor
|
// If zeroed tile and last tile was not raw, use the last backgroundColor
|
||||||
this.applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
|
applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
|
||||||
}
|
}
|
||||||
} else if (subEncoding & 0x01) {
|
} else if (subEncoding & 0x01) {
|
||||||
// If Raw, ignore all other bits
|
// If Raw, ignore all other bits
|
||||||
|
@ -50,7 +48,7 @@ export class HextileDecoder {
|
||||||
dataSize += th * tw * (bitsPerPixel / 8);
|
dataSize += th * tw * (bitsPerPixel / 8);
|
||||||
for (let h = 0; h < th; h++) {
|
for (let h = 0; h < th; h++) {
|
||||||
for (let w = 0; w < tw; w++) {
|
for (let w = 0; w < tw; w++) {
|
||||||
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
const fbBytePosOffset = getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
||||||
if (bitsPerPixel === 8) {
|
if (bitsPerPixel === 8) {
|
||||||
const index = socket.readUInt8();
|
const index = socket.readUInt8();
|
||||||
const color = colorMap[index];
|
const color = colorMap[index];
|
||||||
|
@ -148,7 +146,7 @@ export class HextileDecoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize tile with the background color
|
// Initialize tile with the background color
|
||||||
this.applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
|
applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
|
||||||
|
|
||||||
// AnySubrects bit
|
// AnySubrects bit
|
||||||
if (subEncoding & 0x08) {
|
if (subEncoding & 0x08) {
|
||||||
|
@ -206,13 +204,13 @@ export class HextileDecoder {
|
||||||
const sw = (wh >> 4) + 1;
|
const sw = (wh >> 4) + 1;
|
||||||
const sh = (wh & 0x0f) + 1;
|
const sh = (wh & 0x0f) + 1;
|
||||||
|
|
||||||
this.applyColor(sw, sh, tx + sx, ty + sy, screenW, screenH, color, fb);
|
applyColor(sw, sh, tx + sx, ty + sy, screenW, screenH, color, fb);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
|
applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
|
applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastSubEncoding = subEncoding;
|
lastSubEncoding = subEncoding;
|
||||||
|
@ -226,16 +224,5 @@ export class HextileDecoder {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply color to a rect on buffer
|
|
||||||
applyColor(tw, th, tx, ty, screenW, screenH, color, fb) {
|
|
||||||
for (let h = 0; h < th; h++) {
|
|
||||||
for (let w = 0; w < tw; w++) {
|
|
||||||
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
|
||||||
fb.writeUInt8(color.r || 255, fbBytePosOffset + 2);
|
|
||||||
fb.writeUInt8(color.g || 255, fbBytePosOffset + 1);
|
|
||||||
fb.writeUInt8(color.b || 255, fbBytePosOffset);
|
|
||||||
fb.writeUInt8(255, fbBytePosOffset + 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
export class RawDecoder {
|
import { SocketBuffer } from "../socketbuffer";
|
||||||
getPixelBytePos(x, y, width, height) {
|
import { IRectDecoder } from "./decoder";
|
||||||
return (y * width + x) * 4;
|
import { getPixelBytePos } from "./util";
|
||||||
}
|
|
||||||
|
|
||||||
async decode(rect, fb, bitsPerPixel, colorMap, screenW, screenH, socket, depth): Promise<void> {
|
import { VncRectangle, Color3 } from "../types";
|
||||||
|
|
||||||
|
export class RawDecoder implements IRectDecoder {
|
||||||
|
|
||||||
|
async decode(rect: VncRectangle, fb: Buffer, bitsPerPixel: number, colorMap: Array<Color3>, screenW: number, screenH: number, socket: SocketBuffer, depth: number): Promise<void> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
await socket.waitBytes(rect.width * rect.height * (bitsPerPixel / 8));
|
await socket.waitBytes(rect.width * rect.height * (bitsPerPixel / 8));
|
||||||
rect.data = socket.readNBytesOffset(rect.width * rect.height * (bitsPerPixel / 8));
|
rect.data = socket.readNBytesOffset(rect.width * rect.height * (bitsPerPixel / 8));
|
||||||
|
|
||||||
for (let h = 0; h < rect.height; h++) {
|
for (let h = 0; h < rect.height; h++) {
|
||||||
for (let w = 0; w < rect.width; w++) {
|
for (let w = 0; w < rect.width; w++) {
|
||||||
const fbBytePosOffset = this.getPixelBytePos(rect.x + w, rect.y + h, screenW, screenH);
|
const fbBytePosOffset = getPixelBytePos(rect.x + w, rect.y + h, screenW, screenH);
|
||||||
if (bitsPerPixel === 8) {
|
if (bitsPerPixel === 8) {
|
||||||
const bytePosOffset = h * rect.width + w;
|
const bytePosOffset = h * rect.width + w;
|
||||||
const index = rect.data.readUInt8(bytePosOffset);
|
const index = rect.data.readUInt8(bytePosOffset);
|
||||||
|
|
19
qemu/src/rfb/decoders/util.ts
Normal file
19
qemu/src/rfb/decoders/util.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
import { Color3 } from "../types";
|
||||||
|
|
||||||
|
export function getPixelBytePos(x: number, y: number, width: number, height: number, stride: number = 4): number {
|
||||||
|
return (y * width + x) * stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply color to a rect on buffer
|
||||||
|
export function applyColor(tw: number, th: number, tx: number, ty: number, screenW: number, screenH: number, color: Color3, fb: Buffer) {
|
||||||
|
for (let h = 0; h < th; h++) {
|
||||||
|
for (let w = 0; w < tw; w++) {
|
||||||
|
const fbBytePosOffset = getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
||||||
|
fb.writeUInt8(color.r || 255, fbBytePosOffset + 2);
|
||||||
|
fb.writeUInt8(color.g || 255, fbBytePosOffset + 1);
|
||||||
|
fb.writeUInt8(color.b || 255, fbBytePosOffset);
|
||||||
|
fb.writeUInt8(255, fbBytePosOffset + 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,11 @@
|
||||||
import * as zlib from 'node:zlib';
|
import * as zlib from 'node:zlib';
|
||||||
import { SocketBuffer } from '../socketbuffer.js';
|
import { SocketBuffer } from "../socketbuffer";
|
||||||
|
import { IRectDecoder } from "./decoder";
|
||||||
|
import { applyColor, getPixelBytePos } from "./util";
|
||||||
|
|
||||||
export class ZrleDecoder {
|
import { VncRectangle, Color3, Color4 } from "../types";
|
||||||
|
|
||||||
|
export class ZrleDecoder implements IRectDecoder {
|
||||||
private zlib: zlib.Inflate;
|
private zlib: zlib.Inflate;
|
||||||
private unBuffer: SocketBuffer;
|
private unBuffer: SocketBuffer;
|
||||||
|
|
||||||
|
@ -14,11 +18,7 @@ export class ZrleDecoder {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getPixelBytePos(x, y, width, height) {
|
async decode(rect: VncRectangle, fb: Buffer, bitsPerPixel: number, colorMap: Array<Color3>, screenW: number, screenH: number, socket: SocketBuffer, depth: number): Promise<void> {
|
||||||
return (y * width + x) * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
async decode(rect, fb, bitsPerPixel, colorMap, screenW, screenH, socket, depth): Promise<void> {
|
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
await socket.waitBytes(4);
|
await socket.waitBytes(4);
|
||||||
|
|
||||||
|
@ -35,15 +35,10 @@ export class ZrleDecoder {
|
||||||
this.zlib.write(compressedData, async () => {
|
this.zlib.write(compressedData, async () => {
|
||||||
this.zlib.flush();
|
this.zlib.flush();
|
||||||
|
|
||||||
let tiles;
|
let tilesX = Math.ceil(rect.width / 64);
|
||||||
let totalTiles;
|
let tilesY = Math.ceil(rect.height / 64);
|
||||||
let tilesX;
|
let tiles = tilesX * tilesY;
|
||||||
let tilesY;
|
let totalTiles = tiles;
|
||||||
|
|
||||||
tilesX = Math.ceil(rect.width / 64);
|
|
||||||
tilesY = Math.ceil(rect.height / 64);
|
|
||||||
tiles = tilesX * tilesY;
|
|
||||||
totalTiles = tiles;
|
|
||||||
|
|
||||||
while (tiles) {
|
while (tiles) {
|
||||||
await this.unBuffer.waitBytes(1, 'tile begin.');
|
await this.unBuffer.waitBytes(1, 'tile begin.');
|
||||||
|
@ -67,7 +62,7 @@ export class ZrleDecoder {
|
||||||
// Raw
|
// Raw
|
||||||
for (let h = 0; h < th; h++) {
|
for (let h = 0; h < th; h++) {
|
||||||
for (let w = 0; w < tw; w++) {
|
for (let w = 0; w < tw; w++) {
|
||||||
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
const fbBytePosOffset = getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
||||||
if (bitsPerPixel === 8) {
|
if (bitsPerPixel === 8) {
|
||||||
await this.unBuffer.waitBytes(1, 'raw 8bits');
|
await this.unBuffer.waitBytes(1, 'raw 8bits');
|
||||||
const index = this.unBuffer.readUInt8();
|
const index = this.unBuffer.readUInt8();
|
||||||
|
@ -105,11 +100,11 @@ export class ZrleDecoder {
|
||||||
}
|
}
|
||||||
} else if (subEncoding === 1) {
|
} else if (subEncoding === 1) {
|
||||||
// Single Color
|
// Single Color
|
||||||
let color = { r: 0, g: 0, b: 0, a: 255 };
|
let color: Color4 = { r: 0, g: 0, b: 0, a: 255 };
|
||||||
if (bitsPerPixel === 8) {
|
if (bitsPerPixel === 8) {
|
||||||
await this.unBuffer.waitBytes(1, 'single color 8bits');
|
await this.unBuffer.waitBytes(1, 'single color 8bits');
|
||||||
const index = this.unBuffer.readUInt8();
|
const index = this.unBuffer.readUInt8();
|
||||||
color = colorMap[index];
|
color = (colorMap[index] as Color4);
|
||||||
} else if (bitsPerPixel === 24 || (bitsPerPixel === 32 && depth === 24)) {
|
} else if (bitsPerPixel === 24 || (bitsPerPixel === 32 && depth === 24)) {
|
||||||
await this.unBuffer.waitBytes(3, 'single color 24bits');
|
await this.unBuffer.waitBytes(3, 'single color 24bits');
|
||||||
color.r = this.unBuffer.readUInt8();
|
color.r = this.unBuffer.readUInt8();
|
||||||
|
@ -122,7 +117,7 @@ export class ZrleDecoder {
|
||||||
color.b = this.unBuffer.readUInt8();
|
color.b = this.unBuffer.readUInt8();
|
||||||
color.a = this.unBuffer.readUInt8();
|
color.a = this.unBuffer.readUInt8();
|
||||||
}
|
}
|
||||||
this.applyColor(tw, th, tx, ty, screenW, screenH, color, fb);
|
applyColor(tw, th, tx, ty, screenW, screenH, color, fb);
|
||||||
} else if (subEncoding >= 2 && subEncoding <= 16) {
|
} else if (subEncoding >= 2 && subEncoding <= 16) {
|
||||||
// Palette
|
// Palette
|
||||||
const palette = [];
|
const palette = [];
|
||||||
|
@ -152,7 +147,7 @@ export class ZrleDecoder {
|
||||||
// const i = (tw * th) / (8 / bitsPerIndex);
|
// const i = (tw * th) / (8 / bitsPerIndex);
|
||||||
// const pixels = [];
|
// const pixels = [];
|
||||||
|
|
||||||
let byte;
|
let byte = 0;
|
||||||
let bitPos = 0;
|
let bitPos = 0;
|
||||||
|
|
||||||
for (let h = 0; h < th; h++) {
|
for (let h = 0; h < th; h++) {
|
||||||
|
@ -162,7 +157,7 @@ export class ZrleDecoder {
|
||||||
byte = this.unBuffer.readUInt8();
|
byte = this.unBuffer.readUInt8();
|
||||||
bitPos = 0;
|
bitPos = 0;
|
||||||
}
|
}
|
||||||
let color;
|
let color : Color4 = { r: 0, g: 0, b: 0, a: 255 };
|
||||||
switch (bitsPerIndex) {
|
switch (bitsPerIndex) {
|
||||||
case 1:
|
case 1:
|
||||||
if (bitPos === 0) {
|
if (bitPos === 0) {
|
||||||
|
@ -216,7 +211,7 @@ export class ZrleDecoder {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
const fbBytePosOffset = getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
||||||
fb.writeUInt8(color.b ?? 0, fbBytePosOffset);
|
fb.writeUInt8(color.b ?? 0, fbBytePosOffset);
|
||||||
fb.writeUInt8(color.g ?? 0, fbBytePosOffset + 1);
|
fb.writeUInt8(color.g ?? 0, fbBytePosOffset + 1);
|
||||||
fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2);
|
fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2);
|
||||||
|
@ -259,7 +254,7 @@ export class ZrleDecoder {
|
||||||
totalRun += runLength;
|
totalRun += runLength;
|
||||||
runs++;
|
runs++;
|
||||||
}
|
}
|
||||||
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
const fbBytePosOffset = getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
||||||
fb.writeUInt8(color.b ?? 0, fbBytePosOffset);
|
fb.writeUInt8(color.b ?? 0, fbBytePosOffset);
|
||||||
fb.writeUInt8(color.g ?? 0, fbBytePosOffset + 1);
|
fb.writeUInt8(color.g ?? 0, fbBytePosOffset + 1);
|
||||||
fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2);
|
fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2);
|
||||||
|
@ -321,7 +316,7 @@ export class ZrleDecoder {
|
||||||
totalRun += runLength;
|
totalRun += runLength;
|
||||||
runs++;
|
runs++;
|
||||||
}
|
}
|
||||||
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
const fbBytePosOffset = getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
||||||
fb.writeUInt8(color.b ?? 0, fbBytePosOffset);
|
fb.writeUInt8(color.b ?? 0, fbBytePosOffset);
|
||||||
fb.writeUInt8(color.g ?? 0, fbBytePosOffset + 1);
|
fb.writeUInt8(color.g ?? 0, fbBytePosOffset + 1);
|
||||||
fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2);
|
fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2);
|
||||||
|
@ -342,16 +337,4 @@ export class ZrleDecoder {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply color to a rect on buffer
|
|
||||||
applyColor(tw, th, tx, ty, screenW, screenH, color, fb) {
|
|
||||||
for (let h = 0; h < th; h++) {
|
|
||||||
for (let w = 0; w < tw; w++) {
|
|
||||||
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH);
|
|
||||||
fb.writeUInt8(color.b || 255, fbBytePosOffset);
|
|
||||||
fb.writeUInt8(color.g || 255, fbBytePosOffset + 1);
|
|
||||||
fb.writeUInt8(color.r || 255, fbBytePosOffset + 2);
|
|
||||||
fb.writeUInt8(255, fbBytePosOffset + 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
/// this is a pretty poor name.
|
/// this is a pretty poor name.
|
||||||
export class SocketBuffer {
|
export class SocketBuffer {
|
||||||
public buffer?: Buffer;
|
public buffer: Buffer;
|
||||||
private offset: number;
|
public offset: number; // :(
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.buffer = Buffer.from([]);
|
||||||
|
this.offset = 0;
|
||||||
this.flush();
|
this.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,11 +23,11 @@ export class SocketBuffer {
|
||||||
return this.buffer.toString();
|
return this.buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
includes(check) {
|
includes(check: Buffer|number|string) {
|
||||||
return this.buffer.includes(check);
|
return this.buffer.includes(check);
|
||||||
}
|
}
|
||||||
|
|
||||||
pushData(data) {
|
pushData(data: Buffer) {
|
||||||
this.buffer = Buffer.concat([this.buffer, data]);
|
this.buffer = Buffer.concat([this.buffer, data]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,17 +79,17 @@ export class SocketBuffer {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
readNBytes(bytes, offset = this.offset) {
|
readNBytes(bytes: number, offset = this.offset) {
|
||||||
return this.buffer.slice(offset, offset + bytes);
|
return this.buffer.slice(offset, offset + bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
readNBytesOffset(bytes) {
|
readNBytesOffset(bytes: number) {
|
||||||
const data = this.buffer.slice(this.offset, this.offset + bytes);
|
const data = this.buffer.slice(this.offset, this.offset + bytes);
|
||||||
this.offset += bytes;
|
this.offset += bytes;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
setOffset(n) {
|
setOffset(n: number) {
|
||||||
this.offset = n;
|
this.offset = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +98,7 @@ export class SocketBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// name is nullable because there are Many(yay....) times it just isn't passed
|
// name is nullable because there are Many(yay....) times it just isn't passed
|
||||||
waitBytes(bytes, name: any | null = null): Promise<void> {
|
async waitBytes(bytes: number, name: any | null = null): Promise<void> {
|
||||||
if (this.bytesLeft() >= bytes) {
|
if (this.bytesLeft() >= bytes) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -114,17 +116,17 @@ export class SocketBuffer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fill(data) {
|
fill(data: Buffer) {
|
||||||
this.buffer.fill(data, this.offset, this.offset + data.length);
|
this.buffer.fill(data, this.offset, this.offset + data.length);
|
||||||
this.offset += data.length;
|
this.offset += data.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
fillMultiple(data, repeats) {
|
fillMultiple(data: Buffer, repeats: number) {
|
||||||
this.buffer.fill(data, this.offset, this.offset + data.length * repeats);
|
this.buffer.fill(data, this.offset, this.offset + data.length * repeats);
|
||||||
this.offset += data.length * repeats;
|
this.offset += data.length * repeats;
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(n): Promise<void> {
|
sleep(n: number): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
setTimeout(resolve, n);
|
setTimeout(resolve, n);
|
||||||
});
|
});
|
||||||
|
|
44
qemu/src/rfb/types.ts
Normal file
44
qemu/src/rfb/types.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
export type Rect = {
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type VncRectangle = Rect & {
|
||||||
|
encoding: number,
|
||||||
|
data: Buffer | null // ?
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type PixelFormat = {
|
||||||
|
bitsPerPixel: number,
|
||||||
|
depth: number,
|
||||||
|
bigEndianFlag: number,
|
||||||
|
trueColorFlag: number,
|
||||||
|
redMax: number,
|
||||||
|
greenMax: number,
|
||||||
|
blueMax: number,
|
||||||
|
redShift: number,
|
||||||
|
blueShift: number,
|
||||||
|
greenShift: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Cursor = Rect & {
|
||||||
|
cursorPixels: Buffer|null,
|
||||||
|
bitmask: Buffer|null,
|
||||||
|
|
||||||
|
posX: number,
|
||||||
|
posY: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Color3 = {
|
||||||
|
r: number,
|
||||||
|
g: number,
|
||||||
|
b: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Color4 = Color3 & {
|
||||||
|
a: number,
|
||||||
|
};
|
||||||
|
|
|
@ -4,14 +4,29 @@
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"description": "crusttest shared bits",
|
"description": "crusttest shared bits",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/src/index.js",
|
"main": "dist/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
|
|
||||||
"devDependencies": {},
|
"targets": {
|
||||||
|
"types": {},
|
||||||
|
"shared":{
|
||||||
|
"context": "browser",
|
||||||
|
"isLibrary": true,
|
||||||
|
"outputFormat": "esmodule"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"dependencies": {
|
||||||
|
},
|
||||||
|
|
||||||
|
"devDependencies": {
|
||||||
|
"parcel": "^2.12.0"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc"
|
"build": "parcel build src/index.ts --target shared --target types"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
|
|
|
@ -103,84 +103,90 @@ export type DeserializedMessage = AnyMessage;
|
||||||
export const kProtocolHeaderSize = 8;
|
export const kProtocolHeaderSize = 8;
|
||||||
|
|
||||||
export class MessageEncoder {
|
export class MessageEncoder {
|
||||||
private struct: Struct;
|
private struct: Struct|null = null;
|
||||||
private buffer: ArrayBuffer;
|
private buffer: ArrayBuffer|null = null;
|
||||||
|
|
||||||
Init(byteSize) {
|
Init(byteSize: number) {
|
||||||
this.buffer = new ArrayBuffer(byteSize + kProtocolHeaderSize);
|
this.buffer = new ArrayBuffer(byteSize + kProtocolHeaderSize);
|
||||||
this.struct = new Struct(this.buffer);
|
this.struct = new Struct(this.buffer);
|
||||||
this.InitHeader();
|
this.InitHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
SetKeyMessage(keysym, pressed) {
|
SetKeyMessage(keysym: number, pressed: boolean) {
|
||||||
this.SetTypeCode(MessageType.Key);
|
this.SetTypeCode(MessageType.Key);
|
||||||
this.struct.WriteU16(keysym);
|
this.struct?.WriteU16(keysym);
|
||||||
this.struct.WriteU8(pressed == true ? 1 : 0);
|
this.struct?.WriteU8(pressed == true ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetMouseMessage(x, y, buttons: MouseButtons) {
|
SetMouseMessage(x: number, y: number, buttons: MouseButtons) {
|
||||||
this.SetTypeCode(MessageType.Mouse);
|
this.SetTypeCode(MessageType.Mouse);
|
||||||
this.struct.WriteU16(x);
|
this.struct?.WriteU16(x);
|
||||||
this.struct.WriteU16(y);
|
this.struct?.WriteU16(y);
|
||||||
this.struct.WriteU8(buttons);
|
this.struct?.WriteU8(buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetTurnMessage() {
|
SetTurnMessage() {
|
||||||
this.SetTypeCode(MessageType.Turn);
|
this.SetTypeCode(MessageType.Turn);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetTurnSrvMessage(ms, usersQueue) {
|
SetTurnSrvMessage(ms: number, usersQueue: Array<string>) {
|
||||||
this.SetTypeCode(MessageType.Turn);
|
this.SetTypeCode(MessageType.Turn);
|
||||||
this.struct.WriteU32(ms);
|
this.struct?.WriteU32(ms);
|
||||||
this.struct.WriteArray(usersQueue, this.struct.WriteString);
|
this.struct?.WriteArray(usersQueue, this.struct?.WriteString);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDisplayRectMessage(x, y, buffer: ArrayBuffer) {
|
SetDisplayRectMessage(x: number, y: number, buffer: ArrayBuffer) {
|
||||||
this.SetTypeCode(MessageType.DisplayRect);
|
this.SetTypeCode(MessageType.DisplayRect);
|
||||||
this.struct.WriteU16(x);
|
this.struct?.WriteU16(x);
|
||||||
this.struct.WriteU16(y);
|
this.struct?.WriteU16(y);
|
||||||
this.struct.WriteBuffer(buffer);
|
this.struct?.WriteBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDisplaySizeMessage(w, h) {
|
SetDisplaySizeMessage(w: number, h: number) {
|
||||||
this.SetTypeCode(MessageType.DisplaySize);
|
this.SetTypeCode(MessageType.DisplaySize);
|
||||||
this.struct.WriteU16(w);
|
this.struct?.WriteU16(w);
|
||||||
this.struct.WriteU16(h);
|
this.struct?.WriteU16(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SetAddUserMessage(user: string) {
|
SetAddUserMessage(user: string) {
|
||||||
this.SetTypeCode(MessageType.AddUser);
|
this.SetTypeCode(MessageType.AddUser);
|
||||||
this.struct.WriteString(user);
|
this.struct?.WriteString(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetRemUserMessage(user: string) {
|
SetRemUserMessage(user: string) {
|
||||||
this.SetTypeCode(MessageType.RemUser);
|
this.SetTypeCode(MessageType.RemUser);
|
||||||
this.struct.WriteString(user);
|
this.struct?.WriteString(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Setup some stuff and then return the final message
|
// Setup some stuff and then return the final message
|
||||||
Finish() {
|
Finish() {
|
||||||
let endOffset = this.struct.Tell();
|
if(this.struct == null || this.buffer == null)
|
||||||
this.struct.Seek(4); // seek to size offset
|
throw new Error('no');
|
||||||
this.struct.WriteU32(endOffset - kProtocolHeaderSize);
|
|
||||||
this.struct.Seek(endOffset);
|
let endOffset :number = this.struct?.Tell();
|
||||||
return this.buffer.slice(0, endOffset);
|
this.struct?.Seek(4); // seek to size offset
|
||||||
|
this.struct?.WriteU32(endOffset - kProtocolHeaderSize);
|
||||||
|
this.struct?.Seek(endOffset);
|
||||||
|
return this.buffer?.slice(0, endOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
private InitHeader() {
|
private InitHeader() {
|
||||||
this.struct.Seek(0);
|
this.struct?.Seek(0);
|
||||||
this.struct.WriteU16(kProtocolMagic);
|
this.struct?.WriteU16(kProtocolMagic);
|
||||||
this.struct.WriteU16(0); // No message type yet
|
this.struct?.WriteU16(0); // No message type yet
|
||||||
this.struct.WriteU32(0); // No payload size yet
|
this.struct?.WriteU32(0); // No payload size yet
|
||||||
}
|
}
|
||||||
|
|
||||||
private SetTypeCode(type: MessageType) {
|
private SetTypeCode(type: MessageType) {
|
||||||
let oldOff = this.struct.Tell();
|
if(this.struct == null)
|
||||||
this.struct.Seek(2); // seek to type offset
|
throw new Error('no');
|
||||||
this.struct.WriteU16(type);
|
|
||||||
this.struct.Seek(oldOff);
|
let oldOff = this.struct?.Tell();
|
||||||
|
this.struct?.Seek(2); // seek to type offset
|
||||||
|
this.struct?.WriteU16(type);
|
||||||
|
this.struct?.Seek(oldOff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,14 +195,17 @@ export class MessageDecoder {
|
||||||
|
|
||||||
static async ReadMessage(buffer: ArrayBuffer, asClient: boolean): Promise<DeserializedMessage> {
|
static async ReadMessage(buffer: ArrayBuffer, asClient: boolean): Promise<DeserializedMessage> {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
MessageDecoder.ReadMessageSync(buffer, asClient, (err: Error, message: DeserializedMessage) => {
|
MessageDecoder.ReadMessageSync(buffer, asClient, (err: Error|null, message: DeserializedMessage|null) => {
|
||||||
if (err) rej(err);
|
if (err) rej(err);
|
||||||
|
|
||||||
|
if(message != null) {
|
||||||
res(message);
|
res(message);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReadMessageSync(buffer: ArrayBuffer, asClient: boolean, callback: (err: Error, message:DeserializedMessage) => void) {
|
private static ReadMessageSync(buffer: ArrayBuffer, asClient: boolean, callback: (err: Error|null, message: DeserializedMessage|null) => void) {
|
||||||
let struct = new Struct(buffer);
|
let struct = new Struct(buffer);
|
||||||
|
|
||||||
// Read and verify the header
|
// Read and verify the header
|
||||||
|
|
|
@ -36,7 +36,7 @@ export class Struct {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadStringLen(maxStringLength) {
|
ReadStringLen(maxStringLength: number) {
|
||||||
let stringLength = this.ReadU32();
|
let stringLength = this.ReadU32();
|
||||||
let s = '';
|
let s = '';
|
||||||
|
|
||||||
|
@ -97,20 +97,21 @@ export class Struct {
|
||||||
// then copying
|
// then copying
|
||||||
|
|
||||||
// Add an array with a fixed type
|
// Add an array with a fixed type
|
||||||
WriteArray(arr, functor) {
|
WriteArray(arr: any[], functor: any) {
|
||||||
this.WriteU32(arr.length);
|
this.WriteU32(arr.length);
|
||||||
for (let elem of arr) functor.call(this, elem);
|
for (let elem of arr) functor.call(this, elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a pascal UTF-16 string.
|
// Add a pascal UTF-16 string.
|
||||||
WriteString(str) {
|
WriteString(str: string) {
|
||||||
this.WriteU32(str.length);
|
this.WriteU32(str.length);
|
||||||
for (let i in str) this.WriteU16(str.charCodeAt(i));
|
for (var i = 0; i < str.length; ++i)
|
||||||
|
this.WriteU16(str.charCodeAt(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes a string with a max length.
|
// writes a string with a max length.
|
||||||
// will trim strings that are too long
|
// will trim strings that are too long
|
||||||
WriteStringLen(str, len) {
|
WriteStringLen(str: string, len: number) {
|
||||||
let length = len;
|
let length = len;
|
||||||
|
|
||||||
// pick the string length, but ONLY
|
// pick the string length, but ONLY
|
||||||
|
@ -125,38 +126,39 @@ export class Struct {
|
||||||
this.WriteU16(str.charCodeAt(i));
|
this.WriteU16(str.charCodeAt(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteU8(i) {
|
WriteU8(i: number) {
|
||||||
this.dv.setUint8(this.byteOffset, i);
|
this.dv.setUint8(this.byteOffset, i);
|
||||||
this.byteOffset++;
|
this.byteOffset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteS8(i) {
|
WriteS8(i: number) {
|
||||||
this.dv.setInt8(this.byteOffset, i);
|
this.dv.setInt8(this.byteOffset, i);
|
||||||
this.byteOffset++;
|
this.byteOffset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteU16(i) {
|
WriteU16(i: number) {
|
||||||
this.dv.setUint16(this.byteOffset, i, false);
|
this.dv.setUint16(this.byteOffset, i, false);
|
||||||
this.byteOffset += 2;
|
this.byteOffset += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteS16(i) {
|
WriteS16(i: number) {
|
||||||
this.dv.setInt16(this.byteOffset, i, false);
|
this.dv.setInt16(this.byteOffset, i, false);
|
||||||
this.byteOffset += 2;
|
this.byteOffset += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteU32(i) {
|
WriteU32(i: number) {
|
||||||
this.dv.setUint32(this.byteOffset, i, false);
|
this.dv.setUint32(this.byteOffset, i, false);
|
||||||
this.byteOffset += 4;
|
this.byteOffset += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteS32(i) {
|
WriteS32(i: number) {
|
||||||
this.dv.setInt32(this.byteOffset, i, false);
|
this.dv.setInt32(this.byteOffset, i, false);
|
||||||
this.byteOffset += 4;
|
this.byteOffset += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteBuffer(buffer: ArrayBuffer) {
|
WriteBuffer(buffer: ArrayBuffer) {
|
||||||
|
let u8ar = new Uint8Array(buffer);
|
||||||
this.WriteU32(buffer.byteLength);
|
this.WriteU32(buffer.byteLength);
|
||||||
for (let i = 0; i < buffer.byteLength; ++i) this.WriteU8(buffer[i]);
|
for (let i = 0; i < buffer.byteLength; ++i) this.WriteU8(u8ar[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
// This is the base tsconfig
|
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "ES2021",
|
|
||||||
"module": "ES2020",
|
|
||||||
"moduleResolution": "Node",
|
|
||||||
"declaration": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
|
|
||||||
// more compiler options?
|
|
||||||
"strict": false, // maybe enable later..?
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +1,10 @@
|
||||||
|
// This is the base tsconfig the entire Socket2 project uses
|
||||||
{
|
{
|
||||||
"files": [],
|
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"declaration": true,
|
"target": "ES2022",
|
||||||
"declarationMap": true,
|
"module": "ES2022",
|
||||||
"noEmitOnError": true,
|
"moduleResolution": "Node",
|
||||||
"skipLibCheck": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"baseUrl": "./",
|
"strict": true,
|
||||||
|
}
|
||||||
"paths": {
|
|
||||||
"@socketcomputer/shared*": [ "shared/src/*" ],
|
|
||||||
"@socketcomputer/backend*": [ "backend/src/*" ],
|
|
||||||
"@socketcomputer/qemu*": [ "qemu/src/*" ]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
"exclude": [
|
|
||||||
"node_modules",
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
|
|
||||||
"references": [
|
|
||||||
{ "path": "./backend" },
|
|
||||||
{ "path": "./qemu" },
|
|
||||||
{ "path": "./shared" },
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,8 @@
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@parcel/transformer-sass": "^2.12.0",
|
"parcel": "^2.12.0"
|
||||||
"parcel": "^2.12.0",
|
|
||||||
"typescript": "^5.4.3"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoevents": "^9.0.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,10 @@ import * as Shared from '@socketcomputer/shared';
|
||||||
import {GetKeysym} from "./keyboard";
|
import {GetKeysym} from "./keyboard";
|
||||||
import {Mouse} from "./mouse";
|
import {Mouse} from "./mouse";
|
||||||
|
|
||||||
|
|
||||||
type UserRecord = {
|
type UserRecord = {
|
||||||
username: string
|
username: string
|
||||||
};
|
};
|
||||||
|
|
||||||
let turnInt: number = -1;
|
|
||||||
|
|
||||||
async function sleep(ms: number) : Promise<void> {
|
async function sleep(ms: number) : Promise<void> {
|
||||||
return new Promise((res) => {
|
return new Promise((res) => {
|
||||||
|
@ -16,7 +14,10 @@ async function sleep(ms: number) : Promise<void> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function waitingTimer(text, ms, dot: boolean = true) {
|
|
||||||
|
let turnInt: number = -1;
|
||||||
|
|
||||||
|
function waitingTimer(text: string, ms: number, dot: boolean = true) {
|
||||||
let dots = '';
|
let dots = '';
|
||||||
let timer = document.querySelector('.turn-timer') as HTMLDivElement;
|
let timer = document.querySelector('.turn-timer') as HTMLDivElement;
|
||||||
|
|
||||||
|
@ -24,6 +25,7 @@ function waitingTimer(text, ms, dot: boolean = true) {
|
||||||
clearInterval(turnInt);
|
clearInterval(turnInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-ignore (for some reason it's assuming these are Node)
|
||||||
turnInt = setInterval(() => {
|
turnInt = setInterval(() => {
|
||||||
ms -= 1000;
|
ms -= 1000;
|
||||||
let seconds = Math.floor(ms / 1000);
|
let seconds = Math.floor(ms / 1000);
|
||||||
|
@ -47,7 +49,7 @@ function waitingTimer(text, ms, dot: boolean = true) {
|
||||||
|
|
||||||
// client for
|
// client for
|
||||||
class SocketClient {
|
class SocketClient {
|
||||||
private websocket: WebSocket = null;
|
private websocket: WebSocket|null = null;
|
||||||
private url = "";
|
private url = "";
|
||||||
|
|
||||||
private selfNamed = false;
|
private selfNamed = false;
|
||||||
|
@ -57,8 +59,8 @@ class SocketClient {
|
||||||
private hasTurn = false;
|
private hasTurn = false;
|
||||||
private mouse = new Mouse();
|
private mouse = new Mouse();
|
||||||
|
|
||||||
private canvas:HTMLCanvasElement = null;
|
private canvas:HTMLCanvasElement|null = null;
|
||||||
private canvasCtx : CanvasRenderingContext2D = null;
|
private canvasCtx : CanvasRenderingContext2D|null = null;
|
||||||
|
|
||||||
|
|
||||||
constructor(url: string, canvas: HTMLCanvasElement) {
|
constructor(url: string, canvas: HTMLCanvasElement) {
|
||||||
|
@ -219,9 +221,9 @@ class SocketClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async onWsClose() {
|
private async onWsClose() {
|
||||||
this.websocket.removeEventListener("open", this.onWsOpen);
|
this.websocket?.removeEventListener("open", this.onWsOpen);
|
||||||
this.websocket.removeEventListener("message", this.onWsMessage);
|
this.websocket?.removeEventListener("message", this.onWsMessage);
|
||||||
this.websocket.removeEventListener("close", this.onWsClose);
|
this.websocket?.removeEventListener("close", this.onWsClose);
|
||||||
this.websocket = null;
|
this.websocket = null;
|
||||||
|
|
||||||
// reset state
|
// reset state
|
||||||
|
@ -245,7 +247,7 @@ class SocketClient {
|
||||||
|
|
||||||
async SendBuffer(buffer: ArrayBuffer): Promise<void> {
|
async SendBuffer(buffer: ArrayBuffer): Promise<void> {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
this.websocket.send(buffer);
|
this.websocket?.send(buffer);
|
||||||
res();
|
res();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -275,8 +277,10 @@ class SocketClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
private resizeDisplay(message: Shared.DisplaySizeMessage) {
|
private resizeDisplay(message: Shared.DisplaySizeMessage) {
|
||||||
this.canvas.width = message.width;
|
if(this.canvas == null)
|
||||||
this.canvas.height = message.height;
|
return;
|
||||||
|
this.canvas!.width = message.width;
|
||||||
|
this.canvas!.height = message.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateUserCount() {
|
private updateUserCount() {
|
||||||
|
@ -327,7 +331,7 @@ class SocketClient {
|
||||||
let blob = new Blob([message.data]);
|
let blob = new Blob([message.data]);
|
||||||
createImageBitmap(blob)
|
createImageBitmap(blob)
|
||||||
.then((image) => {
|
.then((image) => {
|
||||||
this.canvasCtx.drawImage(image, message.x, message.y);
|
this.canvasCtx?.drawImage(image, message.x, message.y);
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error(`Error decoding rect for some reason...`, err);
|
console.error(`Error decoding rect for some reason...`, err);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,19 +1,6 @@
|
||||||
{
|
{
|
||||||
"extends": "../tsconfig-base.json",
|
"extends": "../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"composite": true,
|
"lib": ["DOM"],
|
||||||
"esModuleInterop": true,
|
}
|
||||||
"experimentalDecorators": true,
|
|
||||||
|
|
||||||
"lib": ["DOM", "ESNext"],
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "Node",
|
|
||||||
"target": "ES6",
|
|
||||||
|
|
||||||
"outDir": "./dist",
|
|
||||||
"baseUrl": "."
|
|
||||||
},
|
|
||||||
"references": [
|
|
||||||
{ "path": "../shared" }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
323
yarn.lock
323
yarn.lock
|
@ -83,11 +83,36 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@lezer/common" "^1.0.0"
|
"@lezer/common" "^1.0.0"
|
||||||
|
|
||||||
|
"@lmdb/lmdb-darwin-arm64@2.8.5":
|
||||||
|
version "2.8.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.8.5.tgz#895d8cb16a9d709ce5fedd8b60022903b875e08e"
|
||||||
|
integrity sha512-KPDeVScZgA1oq0CiPBcOa3kHIqU+pTOwRFDIhxvmf8CTNvqdZQYp5cCKW0bUk69VygB2PuTiINFWbY78aR2pQw==
|
||||||
|
|
||||||
|
"@lmdb/lmdb-darwin-x64@2.8.5":
|
||||||
|
version "2.8.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-2.8.5.tgz#ca243534c8b37d5516c557e4624256d18dd63184"
|
||||||
|
integrity sha512-w/sLhN4T7MW1nB3R/U8WK5BgQLz904wh+/SmA2jD8NnF7BLLoUgflCNxOeSPOWp8geP6nP/+VjWzZVip7rZ1ug==
|
||||||
|
|
||||||
|
"@lmdb/lmdb-linux-arm64@2.8.5":
|
||||||
|
version "2.8.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-2.8.5.tgz#b44a8023057e21512eefb9f6120096843b531c1e"
|
||||||
|
integrity sha512-vtbZRHH5UDlL01TT5jB576Zox3+hdyogvpcbvVJlmU5PdL3c5V7cj1EODdh1CHPksRl+cws/58ugEHi8bcj4Ww==
|
||||||
|
|
||||||
|
"@lmdb/lmdb-linux-arm@2.8.5":
|
||||||
|
version "2.8.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-2.8.5.tgz#17bd54740779c3e4324e78e8f747c21416a84b3d"
|
||||||
|
integrity sha512-c0TGMbm2M55pwTDIfkDLB6BpIsgxV4PjYck2HiOX+cy/JWiBXz32lYbarPqejKs9Flm7YVAKSILUducU9g2RVg==
|
||||||
|
|
||||||
"@lmdb/lmdb-linux-x64@2.8.5":
|
"@lmdb/lmdb-linux-x64@2.8.5":
|
||||||
version "2.8.5"
|
version "2.8.5"
|
||||||
resolved "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.8.5.tgz"
|
resolved "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.8.5.tgz"
|
||||||
integrity sha512-Xkc8IUx9aEhP0zvgeKy7IQ3ReX2N8N1L0WPcQwnZweWmOuKfwpS3GRIYqLtK5za/w3E60zhFfNdS+3pBZPytqQ==
|
integrity sha512-Xkc8IUx9aEhP0zvgeKy7IQ3ReX2N8N1L0WPcQwnZweWmOuKfwpS3GRIYqLtK5za/w3E60zhFfNdS+3pBZPytqQ==
|
||||||
|
|
||||||
|
"@lmdb/lmdb-win32-x64@2.8.5":
|
||||||
|
version "2.8.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.8.5.tgz#8233e8762440b0f4632c47a09b1b6f23de8b934c"
|
||||||
|
integrity sha512-4wvrf5BgnR8RpogHhtpCPJMKBmvyZPhhUtEwMJbXh0ni2BucpfF07jlmyM11zRqQ2XIq6PbC2j7W7UCCcm1rRQ==
|
||||||
|
|
||||||
"@mapbox/node-pre-gyp@^1.0.0":
|
"@mapbox/node-pre-gyp@^1.0.0":
|
||||||
version "1.0.11"
|
version "1.0.11"
|
||||||
resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz"
|
resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz"
|
||||||
|
@ -112,11 +137,36 @@
|
||||||
"@lezer/lr" "^1.0.0"
|
"@lezer/lr" "^1.0.0"
|
||||||
json5 "^2.2.1"
|
json5 "^2.2.1"
|
||||||
|
|
||||||
|
"@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.2":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz#44d752c1a2dc113f15f781b7cc4f53a307e3fa38"
|
||||||
|
integrity sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==
|
||||||
|
|
||||||
|
"@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.2":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.2.tgz#f954f34355712212a8e06c465bc06c40852c6bb3"
|
||||||
|
integrity sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==
|
||||||
|
|
||||||
|
"@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.2":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.2.tgz#45c63037f045c2b15c44f80f0393fa24f9655367"
|
||||||
|
integrity sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==
|
||||||
|
|
||||||
|
"@msgpackr-extract/msgpackr-extract-linux-arm@3.0.2":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.2.tgz#35707efeafe6d22b3f373caf9e8775e8920d1399"
|
||||||
|
integrity sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==
|
||||||
|
|
||||||
"@msgpackr-extract/msgpackr-extract-linux-x64@3.0.2":
|
"@msgpackr-extract/msgpackr-extract-linux-x64@3.0.2":
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz"
|
resolved "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz"
|
||||||
integrity sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==
|
integrity sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==
|
||||||
|
|
||||||
|
"@msgpackr-extract/msgpackr-extract-win32-x64@3.0.2":
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz#0f164b726869f71da3c594171df5ebc1c4b0a407"
|
||||||
|
integrity sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==
|
||||||
|
|
||||||
"@parcel/bundler-default@2.12.0":
|
"@parcel/bundler-default@2.12.0":
|
||||||
version "2.12.0"
|
version "2.12.0"
|
||||||
resolved "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.12.0.tgz"
|
resolved "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.12.0.tgz"
|
||||||
|
@ -190,7 +240,7 @@
|
||||||
"@parcel/transformer-react-refresh-wrap" "2.12.0"
|
"@parcel/transformer-react-refresh-wrap" "2.12.0"
|
||||||
"@parcel/transformer-svg" "2.12.0"
|
"@parcel/transformer-svg" "2.12.0"
|
||||||
|
|
||||||
"@parcel/core@^2.12.0", "@parcel/core@2.12.0":
|
"@parcel/core@2.12.0":
|
||||||
version "2.12.0"
|
version "2.12.0"
|
||||||
resolved "https://registry.npmjs.org/@parcel/core/-/core-2.12.0.tgz"
|
resolved "https://registry.npmjs.org/@parcel/core/-/core-2.12.0.tgz"
|
||||||
integrity sha512-s+6pwEj+GfKf7vqGUzN9iSEPueUssCCQrCBUlcAfKrJe0a22hTUCjewpB0I7lNrCIULt8dkndD+sMdOrXsRl6Q==
|
integrity sha512-s+6pwEj+GfKf7vqGUzN9iSEPueUssCCQrCBUlcAfKrJe0a22hTUCjewpB0I7lNrCIULt8dkndD+sMdOrXsRl6Q==
|
||||||
|
@ -415,6 +465,13 @@
|
||||||
"@parcel/utils" "2.12.0"
|
"@parcel/utils" "2.12.0"
|
||||||
posthtml "^0.16.4"
|
posthtml "^0.16.4"
|
||||||
|
|
||||||
|
"@parcel/packager-ts@2.12.0":
|
||||||
|
version "2.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/packager-ts/-/packager-ts-2.12.0.tgz#7422c07ff3a327fdb592f6d707d31bc146590a17"
|
||||||
|
integrity sha512-8wR0BNN2NBD+IIU0tjioK+lRD4p2Qi/fKxDH5ixEW912tRV+Vd4kE8k++U6YQIpSlK4FRnjFod5zYYhNSLuiXg==
|
||||||
|
dependencies:
|
||||||
|
"@parcel/plugin" "2.12.0"
|
||||||
|
|
||||||
"@parcel/packager-wasm@2.12.0":
|
"@parcel/packager-wasm@2.12.0":
|
||||||
version "2.12.0"
|
version "2.12.0"
|
||||||
resolved "https://registry.npmjs.org/@parcel/packager-wasm/-/packager-wasm-2.12.0.tgz"
|
resolved "https://registry.npmjs.org/@parcel/packager-wasm/-/packager-wasm-2.12.0.tgz"
|
||||||
|
@ -667,6 +724,25 @@
|
||||||
posthtml-render "^3.0.0"
|
posthtml-render "^3.0.0"
|
||||||
semver "^7.5.2"
|
semver "^7.5.2"
|
||||||
|
|
||||||
|
"@parcel/transformer-typescript-types@2.12.0":
|
||||||
|
version "2.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/transformer-typescript-types/-/transformer-typescript-types-2.12.0.tgz#63e3fc4d1c5d61e1d3a2d56ff58454cf58b514ca"
|
||||||
|
integrity sha512-uxF4UBMYvbjiV3zHTWMrZX8cFD92VUvD3ArcGi5WEtuVROUm9Sc47o0mOzxKfMFlJu2KOfZVHYlzK9f/UKA2kQ==
|
||||||
|
dependencies:
|
||||||
|
"@parcel/diagnostic" "2.12.0"
|
||||||
|
"@parcel/plugin" "2.12.0"
|
||||||
|
"@parcel/source-map" "^2.1.1"
|
||||||
|
"@parcel/ts-utils" "2.12.0"
|
||||||
|
"@parcel/utils" "2.12.0"
|
||||||
|
nullthrows "^1.1.1"
|
||||||
|
|
||||||
|
"@parcel/ts-utils@2.12.0":
|
||||||
|
version "2.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/ts-utils/-/ts-utils-2.12.0.tgz#47878a6f3baff77d2fa6f9878fe235c9c5d75da8"
|
||||||
|
integrity sha512-zou+W6dcqnXXUOfN5zGM+ePIWbYOhGp8bVB2jICoNkoKmNAHd4l4zeHl5yQXnbZfynVw88cZVqxtXS8tYebelg==
|
||||||
|
dependencies:
|
||||||
|
nullthrows "^1.1.1"
|
||||||
|
|
||||||
"@parcel/types@2.12.0":
|
"@parcel/types@2.12.0":
|
||||||
version "2.12.0"
|
version "2.12.0"
|
||||||
resolved "https://registry.npmjs.org/@parcel/types/-/types-2.12.0.tgz"
|
resolved "https://registry.npmjs.org/@parcel/types/-/types-2.12.0.tgz"
|
||||||
|
@ -694,6 +770,41 @@
|
||||||
chalk "^4.1.0"
|
chalk "^4.1.0"
|
||||||
nullthrows "^1.1.1"
|
nullthrows "^1.1.1"
|
||||||
|
|
||||||
|
"@parcel/watcher-android-arm64@2.4.1":
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz#c2c19a3c442313ff007d2d7a9c2c1dd3e1c9ca84"
|
||||||
|
integrity sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==
|
||||||
|
|
||||||
|
"@parcel/watcher-darwin-arm64@2.4.1":
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz#c817c7a3b4f3a79c1535bfe54a1c2818d9ffdc34"
|
||||||
|
integrity sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==
|
||||||
|
|
||||||
|
"@parcel/watcher-darwin-x64@2.4.1":
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz#1a3f69d9323eae4f1c61a5f480a59c478d2cb020"
|
||||||
|
integrity sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==
|
||||||
|
|
||||||
|
"@parcel/watcher-freebsd-x64@2.4.1":
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz#0d67fef1609f90ba6a8a662bc76a55fc93706fc8"
|
||||||
|
integrity sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-arm-glibc@2.4.1":
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz#ce5b340da5829b8e546bd00f752ae5292e1c702d"
|
||||||
|
integrity sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-arm64-glibc@2.4.1":
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz#6d7c00dde6d40608f9554e73998db11b2b1ff7c7"
|
||||||
|
integrity sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-arm64-musl@2.4.1":
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz#bd39bc71015f08a4a31a47cd89c236b9d6a7f635"
|
||||||
|
integrity sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==
|
||||||
|
|
||||||
"@parcel/watcher-linux-x64-glibc@2.4.1":
|
"@parcel/watcher-linux-x64-glibc@2.4.1":
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz"
|
resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz"
|
||||||
|
@ -704,6 +815,21 @@
|
||||||
resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz"
|
resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz"
|
||||||
integrity sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==
|
integrity sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==
|
||||||
|
|
||||||
|
"@parcel/watcher-win32-arm64@2.4.1":
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz#eb4deef37e80f0b5e2f215dd6d7a6d40a85f8adc"
|
||||||
|
integrity sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==
|
||||||
|
|
||||||
|
"@parcel/watcher-win32-ia32@2.4.1":
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz#94fbd4b497be39fd5c8c71ba05436927842c9df7"
|
||||||
|
integrity sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==
|
||||||
|
|
||||||
|
"@parcel/watcher-win32-x64@2.4.1":
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz#4bf920912f67cae5f2d264f58df81abfea68dadf"
|
||||||
|
integrity sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==
|
||||||
|
|
||||||
"@parcel/watcher@^2.0.7":
|
"@parcel/watcher@^2.0.7":
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
resolved "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz"
|
resolved "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz"
|
||||||
|
@ -739,35 +865,30 @@
|
||||||
"@parcel/utils" "2.12.0"
|
"@parcel/utils" "2.12.0"
|
||||||
nullthrows "^1.1.1"
|
nullthrows "^1.1.1"
|
||||||
|
|
||||||
"@socketcomputer/backend@file:/home/lily/source/socket-revamp/backend":
|
"@swc/core-darwin-arm64@1.4.11":
|
||||||
version "1.0.0"
|
version "1.4.11"
|
||||||
resolved "file:backend"
|
resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.11.tgz#91ef40816e10495a4038a98dc6c8dfcc85d9c59b"
|
||||||
dependencies:
|
integrity sha512-C1j1Qp/IHSelVWdEnT7f0iONWxQz6FAqzjCF2iaL+0vFg4V5f2nlgrueY8vj5pNNzSGhrAlxsMxEIp4dj1MXkg==
|
||||||
"@fastify/websocket" "^10.0.1"
|
|
||||||
"@julusian/jpeg-turbo" "^2.1.0"
|
|
||||||
"@socketcomputer/qemu" "*"
|
|
||||||
"@socketcomputer/shared" "*"
|
|
||||||
canvas "^2.11.2"
|
|
||||||
fastify "^4.26.2"
|
|
||||||
mnemonist "^0.39.8"
|
|
||||||
|
|
||||||
"@socketcomputer/qemu@*", "@socketcomputer/qemu@file:/home/lily/source/socket-revamp/qemu":
|
"@swc/core-darwin-x64@1.4.11":
|
||||||
version "1.0.0"
|
version "1.4.11"
|
||||||
resolved "file:qemu"
|
resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.4.11.tgz#6f71e3cd4687ef5df226ba0b8a20adc52fa7dc9e"
|
||||||
dependencies:
|
integrity sha512-0TTy3Ni8ncgaMCchSQ7FK8ZXQLlamy0FXmGWbR58c+pVZWYZltYPTmheJUvVcR0H2+gPAymRKyfC0iLszDALjg==
|
||||||
canvas "^2.11.2"
|
|
||||||
execa "^8.0.1"
|
|
||||||
split "^1.0.1"
|
|
||||||
|
|
||||||
"@socketcomputer/shared@*", "@socketcomputer/shared@file:/home/lily/source/socket-revamp/shared":
|
"@swc/core-linux-arm-gnueabihf@1.4.11":
|
||||||
version "1.0.0"
|
version "1.4.11"
|
||||||
resolved "file:shared"
|
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.11.tgz#08521822b5510cb506bc49e728f416636ff0306f"
|
||||||
|
integrity sha512-XJLB71uw0rog4DjYAPxFGAuGCBQpgJDlPZZK6MTmZOvI/1t0+DelJ24IjHIxk500YYM26Yv47xPabqFPD7I2zQ==
|
||||||
|
|
||||||
"@socketcomputer/webapp@file:/home/lily/source/socket-revamp/webapp":
|
"@swc/core-linux-arm64-gnu@1.4.11":
|
||||||
version "1.0.0"
|
version "1.4.11"
|
||||||
resolved "file:webapp"
|
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.11.tgz#9485bc591aa573b282d08b168b80a60badb8df9b"
|
||||||
dependencies:
|
integrity sha512-vYQwzJvm/iu052d5Iw27UFALIN5xSrGkPZXxLNMHPySVko2QMNNBv35HLatkEQHbQ3X+VKSW9J9SkdtAvAVRAQ==
|
||||||
nanoevents "^9.0.0"
|
|
||||||
|
"@swc/core-linux-arm64-musl@1.4.11":
|
||||||
|
version "1.4.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.11.tgz#85eecad7aaab7e94b1ff15ab9d95e80a1e95f356"
|
||||||
|
integrity sha512-eV+KduiRYUFjPsvbZuJ9aknQH9Tj0U2/G9oIZSzLx/18WsYi+upzHbgxmIIHJ2VJgfd7nN40RI/hMtxNsUzR/g==
|
||||||
|
|
||||||
"@swc/core-linux-x64-gnu@1.4.11":
|
"@swc/core-linux-x64-gnu@1.4.11":
|
||||||
version "1.4.11"
|
version "1.4.11"
|
||||||
|
@ -779,6 +900,21 @@
|
||||||
resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.11.tgz"
|
resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.11.tgz"
|
||||||
integrity sha512-UkVJToKf0owwQYRnGvjHAeYVDfeimCEcx0VQSbJoN7Iy0ckRZi7YPlmWJU31xtKvikE2bQWCOVe0qbSDqqcWXA==
|
integrity sha512-UkVJToKf0owwQYRnGvjHAeYVDfeimCEcx0VQSbJoN7Iy0ckRZi7YPlmWJU31xtKvikE2bQWCOVe0qbSDqqcWXA==
|
||||||
|
|
||||||
|
"@swc/core-win32-arm64-msvc@1.4.11":
|
||||||
|
version "1.4.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.11.tgz#d836b79d8730bf83e6b38a5b888e83944d6fb233"
|
||||||
|
integrity sha512-35khwkyly7lF5NDSyvIrukBMzxPorgc5iTSDfVO/LvnmN5+fm4lTlrDr4tUfTdOhv3Emy7CsKlsNAeFRJ+Pm+w==
|
||||||
|
|
||||||
|
"@swc/core-win32-ia32-msvc@1.4.11":
|
||||||
|
version "1.4.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.11.tgz#bc60bbdc65134aaa5b214e2aaf209acfce401d17"
|
||||||
|
integrity sha512-Wx8/6f0ufgQF2pbVPsJ2dAmFLwIOW+xBE5fxnb7VnEbGkTgP1qMDWiiAtD9rtvDSuODG3i1AEmAak/2HAc6i6A==
|
||||||
|
|
||||||
|
"@swc/core-win32-x64-msvc@1.4.11":
|
||||||
|
version "1.4.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.11.tgz#92fd6d4e2d70bbd4fda438f02310d998db8c7b7c"
|
||||||
|
integrity sha512-0xRFW6K9UZQH2NVC/0pVB0GJXS45lY24f+6XaPBF1YnMHd8A8GoHl7ugyM5yNUTe2AKhSgk5fJV00EJt/XBtdQ==
|
||||||
|
|
||||||
"@swc/core@^1.3.36":
|
"@swc/core@^1.3.36":
|
||||||
version "1.4.11"
|
version "1.4.11"
|
||||||
resolved "https://registry.npmjs.org/@swc/core/-/core-1.4.11.tgz"
|
resolved "https://registry.npmjs.org/@swc/core/-/core-1.4.11.tgz"
|
||||||
|
@ -829,6 +965,21 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types "~5.26.4"
|
undici-types "~5.26.4"
|
||||||
|
|
||||||
|
"@types/split@^1.0.5":
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/split/-/split-1.0.5.tgz#4bd47164b81d6381db37978d5344b374b6825f6c"
|
||||||
|
integrity sha512-gMiDr4vA6YofTpAkPQtP+5pvStIf3CMYphf32YAG/3RwogNL8ii1CQKDc+sxN62KuxPoRaJXcf2zDCDkEBH4FA==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
"@types/through" "*"
|
||||||
|
|
||||||
|
"@types/through@*":
|
||||||
|
version "0.0.33"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.33.tgz#14ebf599320e1c7851e7d598149af183c6b9ea56"
|
||||||
|
integrity sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/ws@^8.5.10":
|
"@types/ws@^8.5.10":
|
||||||
version "8.5.10"
|
version "8.5.10"
|
||||||
resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz"
|
resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz"
|
||||||
|
@ -1011,7 +1162,7 @@ braces@^3.0.2, braces@~3.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
fill-range "^7.0.1"
|
fill-range "^7.0.1"
|
||||||
|
|
||||||
browserslist@^4.6.6, "browserslist@>= 4.21.0":
|
browserslist@^4.6.6:
|
||||||
version "4.23.0"
|
version "4.23.0"
|
||||||
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz"
|
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz"
|
||||||
integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==
|
integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==
|
||||||
|
@ -1029,6 +1180,11 @@ buffer@^6.0.3:
|
||||||
base64-js "^1.3.1"
|
base64-js "^1.3.1"
|
||||||
ieee754 "^1.2.1"
|
ieee754 "^1.2.1"
|
||||||
|
|
||||||
|
builtin-status-codes@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
||||||
|
integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==
|
||||||
|
|
||||||
callsites@^3.0.0:
|
callsites@^3.0.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
|
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
|
||||||
|
@ -1137,16 +1293,16 @@ color-convert@^2.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
color-name "~1.1.4"
|
color-name "~1.1.4"
|
||||||
|
|
||||||
color-name@~1.1.4:
|
|
||||||
version "1.1.4"
|
|
||||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
|
||||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
|
||||||
|
|
||||||
color-name@1.1.3:
|
color-name@1.1.3:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
|
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
|
||||||
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
||||||
|
|
||||||
|
color-name@~1.1.4:
|
||||||
|
version "1.1.4"
|
||||||
|
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
||||||
|
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||||
|
|
||||||
color-support@^1.1.2, color-support@^1.1.3:
|
color-support@^1.1.2, color-support@^1.1.3:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz"
|
resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz"
|
||||||
|
@ -1229,7 +1385,7 @@ csso@^4.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
css-tree "^1.1.2"
|
css-tree "^1.1.2"
|
||||||
|
|
||||||
debug@^4, debug@^4.0.0, debug@4:
|
debug@4, debug@^4, debug@^4.0.0:
|
||||||
version "4.3.4"
|
version "4.3.4"
|
||||||
resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
|
resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
|
||||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||||
|
@ -1263,12 +1419,7 @@ detect-libc@^1.0.3:
|
||||||
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz"
|
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz"
|
||||||
integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
|
integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
|
||||||
|
|
||||||
detect-libc@^2.0.0:
|
detect-libc@^2.0.0, detect-libc@^2.0.1:
|
||||||
version "2.0.3"
|
|
||||||
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz"
|
|
||||||
integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==
|
|
||||||
|
|
||||||
detect-libc@^2.0.1:
|
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz"
|
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz"
|
||||||
integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==
|
integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==
|
||||||
|
@ -1527,6 +1678,11 @@ fs.realpath@^1.0.0:
|
||||||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||||
|
|
||||||
|
fsevents@~2.3.2:
|
||||||
|
version "2.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||||
|
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||||
|
|
||||||
gauge@^3.0.0:
|
gauge@^3.0.0:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz"
|
resolved "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz"
|
||||||
|
@ -1675,7 +1831,7 @@ inflight@^1.0.4:
|
||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
inherits@^2.0.3, inherits@2:
|
inherits@2, inherits@^2.0.3, inherits@^2.0.4:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
|
@ -1791,6 +1947,36 @@ light-my-request@^5.11.0:
|
||||||
process-warning "^3.0.0"
|
process-warning "^3.0.0"
|
||||||
set-cookie-parser "^2.4.1"
|
set-cookie-parser "^2.4.1"
|
||||||
|
|
||||||
|
lightningcss-darwin-arm64@1.24.1:
|
||||||
|
version "1.24.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.24.1.tgz#551735defa1e092ecf91244ca081f65f10ebd5f0"
|
||||||
|
integrity sha512-1jQ12jBy+AE/73uGQWGSafK5GoWgmSiIQOGhSEXiFJSZxzV+OXIx+a9h2EYHxdJfX864M+2TAxWPWb0Vv+8y4w==
|
||||||
|
|
||||||
|
lightningcss-darwin-x64@1.24.1:
|
||||||
|
version "1.24.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.24.1.tgz#5acb1338ac0aae38e405efd854ed97ba11509eea"
|
||||||
|
integrity sha512-R4R1d7VVdq2mG4igMU+Di8GPf0b64ZLnYVkubYnGG0Qxq1KaXQtAzcLI43EkpnoWvB/kUg8JKCWH4S13NfiLcQ==
|
||||||
|
|
||||||
|
lightningcss-freebsd-x64@1.24.1:
|
||||||
|
version "1.24.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.24.1.tgz#ff692c41ed0bbf37ab5a239db4c2fc04c11195e6"
|
||||||
|
integrity sha512-z6NberUUw5ALES6Ixn2shmjRRrM1cmEn1ZQPiM5IrZ6xHHL5a1lPin9pRv+w6eWfcrEo+qGG6R9XfJrpuY3e4g==
|
||||||
|
|
||||||
|
lightningcss-linux-arm-gnueabihf@1.24.1:
|
||||||
|
version "1.24.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.24.1.tgz#ba41556f4422a6a889553ad897898a314386153e"
|
||||||
|
integrity sha512-NLQLnBQW/0sSg74qLNI8F8QKQXkNg4/ukSTa+XhtkO7v3BnK19TS1MfCbDHt+TTdSgNEBv0tubRuapcKho2EWw==
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-gnu@1.24.1:
|
||||||
|
version "1.24.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.24.1.tgz#6b569b6078634233bc470c4179dd67e535f22d73"
|
||||||
|
integrity sha512-AQxWU8c9E9JAjAi4Qw9CvX2tDIPjgzCTrZCSXKELfs4mCwzxRkHh2RCxX8sFK19RyJoJAjA/Kw8+LMNRHS5qEg==
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-musl@1.24.1:
|
||||||
|
version "1.24.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.24.1.tgz#644abd32c09c87228bfb5dda21e8d3f75da6f731"
|
||||||
|
integrity sha512-JCgH/SrNrhqsguUA0uJUM1PvN5+dVuzPIlXcoWDHSv2OU/BWlj2dUYr3XNzEw748SmNZPfl2NjQrAdzaPOn1lA==
|
||||||
|
|
||||||
lightningcss-linux-x64-gnu@1.24.1:
|
lightningcss-linux-x64-gnu@1.24.1:
|
||||||
version "1.24.1"
|
version "1.24.1"
|
||||||
resolved "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.24.1.tgz"
|
resolved "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.24.1.tgz"
|
||||||
|
@ -1801,6 +1987,11 @@ lightningcss-linux-x64-musl@1.24.1:
|
||||||
resolved "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.24.1.tgz"
|
resolved "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.24.1.tgz"
|
||||||
integrity sha512-HLfzVik3RToot6pQ2Rgc3JhfZkGi01hFetHt40HrUMoeKitLoqUUT5owM6yTZPTytTUW9ukLBJ1pc3XNMSvlLw==
|
integrity sha512-HLfzVik3RToot6pQ2Rgc3JhfZkGi01hFetHt40HrUMoeKitLoqUUT5owM6yTZPTytTUW9ukLBJ1pc3XNMSvlLw==
|
||||||
|
|
||||||
|
lightningcss-win32-x64-msvc@1.24.1:
|
||||||
|
version "1.24.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.24.1.tgz#bd6b562d902e0f92904ac3754c722d9e63e00480"
|
||||||
|
integrity sha512-joEupPjYJ7PjZtDsS5lzALtlAudAbgIBMGJPNeFe5HfdmJXFd13ECmEM+5rXNxYVMRHua2w8132R6ab5Z6K9Ow==
|
||||||
|
|
||||||
lightningcss@^1.22.1:
|
lightningcss@^1.22.1:
|
||||||
version "1.24.1"
|
version "1.24.1"
|
||||||
resolved "https://registry.npmjs.org/lightningcss/-/lightningcss-1.24.1.tgz"
|
resolved "https://registry.npmjs.org/lightningcss/-/lightningcss-1.24.1.tgz"
|
||||||
|
@ -1982,11 +2173,6 @@ nan@^2.17.0:
|
||||||
resolved "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz"
|
resolved "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz"
|
||||||
integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==
|
integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==
|
||||||
|
|
||||||
nanoevents@^9.0.0:
|
|
||||||
version "9.0.0"
|
|
||||||
resolved "https://registry.npmjs.org/nanoevents/-/nanoevents-9.0.0.tgz"
|
|
||||||
integrity sha512-X8pU7IOpgKXVLPxYUI55ymXc8XuBE+uypfEyEFBtHkD1EX9KavYTVc+vXZHFyHKzA1TaZoVDqklLdQBBrxIuAw==
|
|
||||||
|
|
||||||
node-addon-api@^5.0.0:
|
node-addon-api@^5.0.0:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz"
|
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz"
|
||||||
|
@ -2492,6 +2678,11 @@ source-map@^0.6.1:
|
||||||
resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
|
resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
|
||||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||||
|
|
||||||
|
split2@^4.0.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz"
|
||||||
|
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
|
||||||
|
|
||||||
split@^1.0.1:
|
split@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/split/-/split-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/split/-/split-1.0.1.tgz"
|
||||||
|
@ -2499,12 +2690,7 @@ split@^1.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
through "2"
|
through "2"
|
||||||
|
|
||||||
split2@^4.0.0:
|
srcset@4:
|
||||||
version "4.2.0"
|
|
||||||
resolved "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz"
|
|
||||||
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
|
|
||||||
|
|
||||||
srcset@4, srcset@4.0.0:
|
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz"
|
resolved "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz"
|
||||||
integrity sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==
|
integrity sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==
|
||||||
|
@ -2514,18 +2700,21 @@ stable@^0.1.8:
|
||||||
resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz"
|
resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz"
|
||||||
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
|
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
|
||||||
|
|
||||||
|
stream-http@^3.1.0:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.2.0.tgz#1872dfcf24cb15752677e40e5c3f9cc1926028b5"
|
||||||
|
integrity sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==
|
||||||
|
dependencies:
|
||||||
|
builtin-status-codes "^3.0.0"
|
||||||
|
inherits "^2.0.4"
|
||||||
|
readable-stream "^3.6.0"
|
||||||
|
xtend "^4.0.2"
|
||||||
|
|
||||||
stream-shift@^1.0.2:
|
stream-shift@^1.0.2:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz"
|
resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz"
|
||||||
integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==
|
integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==
|
||||||
|
|
||||||
string_decoder@^1.1.1, string_decoder@^1.3.0:
|
|
||||||
version "1.3.0"
|
|
||||||
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz"
|
|
||||||
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
|
||||||
dependencies:
|
|
||||||
safe-buffer "~5.2.0"
|
|
||||||
|
|
||||||
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
||||||
|
@ -2535,6 +2724,13 @@ string_decoder@^1.1.1, string_decoder@^1.3.0:
|
||||||
is-fullwidth-code-point "^3.0.0"
|
is-fullwidth-code-point "^3.0.0"
|
||||||
strip-ansi "^6.0.1"
|
strip-ansi "^6.0.1"
|
||||||
|
|
||||||
|
string_decoder@^1.1.1, string_decoder@^1.3.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz"
|
||||||
|
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "~5.2.0"
|
||||||
|
|
||||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||||
|
@ -2566,7 +2762,7 @@ supports-color@^7.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^4.0.0"
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
svgo@^2.4.0, svgo@^3.0.2:
|
svgo@^2.4.0:
|
||||||
version "2.8.0"
|
version "2.8.0"
|
||||||
resolved "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz"
|
resolved "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz"
|
||||||
integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==
|
integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==
|
||||||
|
@ -2640,7 +2836,7 @@ type-fest@^0.20.2:
|
||||||
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz"
|
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz"
|
||||||
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
|
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
|
||||||
|
|
||||||
typescript@^5.4.3, typescript@>=4.9.5:
|
typescript@^5.4.3:
|
||||||
version "5.4.3"
|
version "5.4.3"
|
||||||
resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz"
|
resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz"
|
||||||
integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==
|
integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==
|
||||||
|
@ -2736,6 +2932,11 @@ ws@^8.0.0:
|
||||||
resolved "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz"
|
resolved "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz"
|
||||||
integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==
|
integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==
|
||||||
|
|
||||||
|
xtend@^4.0.2:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||||
|
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||||
|
|
||||||
y18n@^5.0.5:
|
y18n@^5.0.5:
|
||||||
version "5.0.8"
|
version "5.0.8"
|
||||||
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"
|
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"
|
||||||
|
|
Loading…
Reference in a new issue