port entire project to using parcel + strict TypeScript
Mostly out of cleanliness, and actually bundling the libraries properly. Yes, this includes the backend, because.. why not? It seems to work, at least. The VNC client for instance also is now fully strict TypeScript.
This commit is contained in:
parent
7b9c71d534
commit
4212050ae5
29 changed files with 686 additions and 383 deletions
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,13 +3,26 @@
|
||||||
"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": {
|
||||||
|
"parcel": "^2.12.0",
|
||||||
|
|
||||||
"@fastify/websocket": "^10.0.1",
|
"@fastify/websocket": "^10.0.1",
|
||||||
"@julusian/jpeg-turbo": "^2.1.0",
|
"@julusian/jpeg-turbo": "^2.1.0",
|
||||||
"@socketcomputer/qemu": "*",
|
"@socketcomputer/qemu": "*",
|
||||||
|
|
|
@ -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,7 +148,7 @@ 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 = new ExtendableTimer(15);
|
private timer: ExtendableTimer = new ExtendableTimer(15);
|
||||||
private users: Array<VMUser> = [];
|
private users: Array<VMUser> = [];
|
||||||
|
@ -325,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;
|
||||||
|
|
||||||
|
@ -349,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);
|
||||||
|
|
||||||
|
@ -372,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();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -402,7 +405,7 @@ export type SocketComputerConfig = {
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
||||||
});
|
});
|
||||||
|
@ -442,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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
package.json
11
package.json
|
@ -8,15 +8,20 @@
|
||||||
"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",
|
||||||
|
"parcel": "^2.12.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@parcel/packager-ts": "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",
|
||||||
|
"parcel": "^2.12.0",
|
||||||
"split": "^1.0.1"
|
"split": "^1.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@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,28 @@
|
||||||
"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"
|
||||||
],
|
],
|
||||||
|
|
||||||
|
"targets": {
|
||||||
|
"types": {},
|
||||||
|
"shared":{
|
||||||
|
"context": "browser",
|
||||||
|
"isLibrary": true,
|
||||||
|
"outputFormat": "esmodule"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"dependencies": {
|
||||||
|
"parcel": "^2.12.0"
|
||||||
|
},
|
||||||
"devDependencies": {},
|
"devDependencies": {},
|
||||||
"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" },
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,5 @@
|
||||||
"typescript": "^5.4.3"
|
"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