chore: reformat all code with prettier
This commit is contained in:
@@ -1,12 +1,11 @@
|
|||||||
import { Logger } from '@cvmts/shared';
|
import { Logger } from '@cvmts/shared';
|
||||||
import { Rank, User } from './User.js';
|
import { Rank, User } from './User.js';
|
||||||
|
|
||||||
|
|
||||||
export default class AuthManager {
|
export default class AuthManager {
|
||||||
apiEndpoint: string;
|
apiEndpoint: string;
|
||||||
secretKey: string;
|
secretKey: string;
|
||||||
|
|
||||||
private logger = new Logger("CVMTS.AuthMan");
|
private logger = new Logger('CVMTS.AuthMan');
|
||||||
|
|
||||||
constructor(apiEndpoint: string, secretKey: string) {
|
constructor(apiEndpoint: string, secretKey: string) {
|
||||||
this.apiEndpoint = apiEndpoint;
|
this.apiEndpoint = apiEndpoint;
|
||||||
@@ -14,7 +13,7 @@ export default class AuthManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async Authenticate(token: string, user: User): Promise<JoinResponse> {
|
async Authenticate(token: string, user: User): Promise<JoinResponse> {
|
||||||
var response = await fetch(this.apiEndpoint + '/api/v1/join', {
|
let response = await fetch(this.apiEndpoint + '/api/v1/join', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
@@ -26,7 +25,7 @@ export default class AuthManager {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
var json = (await response.json()) as JoinResponse;
|
let json = (await response.json()) as JoinResponse;
|
||||||
|
|
||||||
if (!json.success) {
|
if (!json.success) {
|
||||||
this.logger.Error(`Failed to query auth server: ${json.error}`);
|
this.logger.Error(`Failed to query auth server: ${json.error}`);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Logger } from "@cvmts/shared";
|
import { Logger } from '@cvmts/shared';
|
||||||
|
|
||||||
export class IPData {
|
export class IPData {
|
||||||
tempMuteExpireTimeout?: NodeJS.Timeout;
|
tempMuteExpireTimeout?: NodeJS.Timeout;
|
||||||
@@ -15,19 +15,17 @@ export class IPData {
|
|||||||
|
|
||||||
// Call when a connection is closed to "release" the ip data
|
// Call when a connection is closed to "release" the ip data
|
||||||
Unref() {
|
Unref() {
|
||||||
if(this.refCount - 1 < 0)
|
if (this.refCount - 1 < 0) this.refCount = 0;
|
||||||
this.refCount = 0;
|
|
||||||
this.refCount--;
|
this.refCount--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class IPDataManager {
|
export class IPDataManager {
|
||||||
static ipDatas = new Map<string, IPData>();
|
static ipDatas = new Map<string, IPData>();
|
||||||
static logger = new Logger("CVMTS.IPDataManager");
|
static logger = new Logger('CVMTS.IPDataManager');
|
||||||
|
|
||||||
static GetIPData(address: string) {
|
static GetIPData(address: string) {
|
||||||
if(IPDataManager.ipDatas.has(address)) {
|
if (IPDataManager.ipDatas.has(address)) {
|
||||||
// Note: We already check for if it exists, so we use ! here
|
// Note: We already check for if it exists, so we use ! here
|
||||||
// because TypeScript can't exactly tell that in this case,
|
// because TypeScript can't exactly tell that in this case,
|
||||||
// only in explicit null or undefined checks
|
// only in explicit null or undefined checks
|
||||||
@@ -35,16 +33,15 @@ export class IPDataManager {
|
|||||||
ref.refCount++;
|
ref.refCount++;
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = new IPData(address);
|
let data = new IPData(address);
|
||||||
data.refCount++;
|
data.refCount++;
|
||||||
IPDataManager.ipDatas.set(address, data);
|
IPDataManager.ipDatas.set(address, data);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ForEachIPData(callback: (d: IPData) => void) {
|
static ForEachIPData(callback: (d: IPData) => void) {
|
||||||
for(let tuple of IPDataManager.ipDatas)
|
for (let tuple of IPDataManager.ipDatas) callback(tuple[1]);
|
||||||
callback(tuple[1]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,11 +49,10 @@ export class IPDataManager {
|
|||||||
// Strictly speaking this will just allow the v8 GC to finally
|
// Strictly speaking this will just allow the v8 GC to finally
|
||||||
// delete the objects, but same difference.
|
// delete the objects, but same difference.
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
for(let tuple of IPDataManager.ipDatas) {
|
for (let tuple of IPDataManager.ipDatas) {
|
||||||
if(tuple[1].refCount == 0) {
|
if (tuple[1].refCount == 0) {
|
||||||
IPDataManager.logger.Info("Deleted ipdata for IP {0}", tuple[0]);
|
IPDataManager.logger.Info('Deleted ipdata for IP {0}', tuple[0]);
|
||||||
IPDataManager.ipDatas.delete(tuple[0]);
|
IPDataManager.ipDatas.delete(tuple[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 15000);
|
}, 15000);
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +1,36 @@
|
|||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
// Class to ratelimit a resource (chatting, logging in, etc)
|
// Class to ratelimit a resource (chatting, logging in, etc)
|
||||||
export default class RateLimiter extends EventEmitter {
|
export default class RateLimiter extends EventEmitter {
|
||||||
private limit : number;
|
private limit: number;
|
||||||
private interval : number;
|
private interval: number;
|
||||||
private requestCount : number;
|
private requestCount: number;
|
||||||
private limiter? : NodeJS.Timeout;
|
private limiter?: NodeJS.Timeout;
|
||||||
private limiterSet : boolean;
|
private limiterSet: boolean;
|
||||||
constructor(limit : number, interval : number) {
|
constructor(limit: number, interval: number) {
|
||||||
super();
|
super();
|
||||||
this.limit = limit;
|
this.limit = limit;
|
||||||
this.interval = interval;
|
this.interval = interval;
|
||||||
this.requestCount = 0;
|
this.requestCount = 0;
|
||||||
this.limiterSet = false;
|
this.limiterSet = false;
|
||||||
}
|
}
|
||||||
// Return value is whether or not the action should be continued
|
// Return value is whether or not the action should be continued
|
||||||
request() : boolean {
|
request(): boolean {
|
||||||
this.requestCount++;
|
this.requestCount++;
|
||||||
if (this.requestCount === this.limit) {
|
if (this.requestCount === this.limit) {
|
||||||
this.emit('limit');
|
this.emit('limit');
|
||||||
clearTimeout(this.limiter);
|
clearTimeout(this.limiter);
|
||||||
this.limiterSet = false;
|
this.limiterSet = false;
|
||||||
this.requestCount = 0;
|
this.requestCount = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!this.limiterSet) {
|
if (!this.limiterSet) {
|
||||||
this.limiter = setTimeout(() => {
|
this.limiter = setTimeout(() => {
|
||||||
this.limiterSet = false;
|
this.limiterSet = false;
|
||||||
this.requestCount = 0;
|
this.requestCount = 0;
|
||||||
}, this.interval * 1000);
|
}, this.interval * 1000);
|
||||||
this.limiterSet = true;
|
this.limiterSet = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export class User {
|
|||||||
TurnRateLimit: RateLimiter;
|
TurnRateLimit: RateLimiter;
|
||||||
VoteRateLimit: RateLimiter;
|
VoteRateLimit: RateLimiter;
|
||||||
|
|
||||||
private logger = new Logger("CVMTS.User");
|
private logger = new Logger('CVMTS.User');
|
||||||
|
|
||||||
constructor(ws: WebSocket, ip: IPData, config: IConfig, username?: string, node?: string) {
|
constructor(ws: WebSocket, ip: IPData, config: IConfig, username?: string, node?: string) {
|
||||||
this.IP = ip;
|
this.IP = ip;
|
||||||
@@ -59,6 +59,7 @@ export class User {
|
|||||||
this.VoteRateLimit = new RateLimiter(3, 3);
|
this.VoteRateLimit = new RateLimiter(3, 3);
|
||||||
this.VoteRateLimit.on('limit', () => this.closeConnection());
|
this.VoteRateLimit.on('limit', () => this.closeConnection());
|
||||||
}
|
}
|
||||||
|
|
||||||
assignGuestName(existingUsers: string[]): string {
|
assignGuestName(existingUsers: string[]): string {
|
||||||
var username;
|
var username;
|
||||||
do {
|
do {
|
||||||
@@ -67,25 +68,30 @@ export class User {
|
|||||||
this.username = username;
|
this.username = username;
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendNop() {
|
sendNop() {
|
||||||
this.socket.send('3.nop;');
|
this.socket.send('3.nop;');
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMsg(msg: string | Buffer) {
|
sendMsg(msg: string | Buffer) {
|
||||||
if (this.socket.readyState !== this.socket.OPEN) return;
|
if (this.socket.readyState !== this.socket.OPEN) return;
|
||||||
clearInterval(this.nopSendInterval);
|
clearInterval(this.nopSendInterval);
|
||||||
this.nopSendInterval = setInterval(() => this.sendNop(), 5000);
|
this.nopSendInterval = setInterval(() => this.sendNop(), 5000);
|
||||||
this.socket.send(msg);
|
this.socket.send(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onNoMsg() {
|
private onNoMsg() {
|
||||||
this.sendNop();
|
this.sendNop();
|
||||||
this.nopRecieveTimeout = setTimeout(() => {
|
this.nopRecieveTimeout = setTimeout(() => {
|
||||||
this.closeConnection();
|
this.closeConnection();
|
||||||
}, 3000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
closeConnection() {
|
closeConnection() {
|
||||||
this.socket.send(guacutils.encode('disconnect'));
|
this.socket.send(guacutils.encode('disconnect'));
|
||||||
this.socket.close();
|
this.socket.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
onMsgSent() {
|
onMsgSent() {
|
||||||
if (!this.Config.collabvm.automute.enabled) return;
|
if (!this.Config.collabvm.automute.enabled) return;
|
||||||
// rate limit guest and unregistered chat messages, but not staff ones
|
// rate limit guest and unregistered chat messages, but not staff ones
|
||||||
@@ -99,6 +105,7 @@ export class User {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mute(permanent: boolean) {
|
mute(permanent: boolean) {
|
||||||
this.IP.muted = true;
|
this.IP.muted = true;
|
||||||
this.sendMsg(guacutils.encode('chat', '', `You have been muted${permanent ? '' : ` for ${this.Config.collabvm.tempMuteTime} seconds`}.`));
|
this.sendMsg(guacutils.encode('chat', '', `You have been muted${permanent ? '' : ` for ${this.Config.collabvm.tempMuteTime} seconds`}.`));
|
||||||
|
|||||||
@@ -1,54 +1,54 @@
|
|||||||
import { Permissions } from "./IConfig";
|
import { Permissions } from './IConfig';
|
||||||
|
|
||||||
export function Randint(min : number, max : number) {
|
export function Randint(min: number, max: number) {
|
||||||
return Math.floor((Math.random() * (max - min)) + min);
|
return Math.floor(Math.random() * (max - min) + min);
|
||||||
}
|
|
||||||
export function HTMLSanitize(input : string) : string {
|
|
||||||
var output = "";
|
|
||||||
for (var i = 0; i < input.length; i++) {
|
|
||||||
switch (input[i]) {
|
|
||||||
case "<":
|
|
||||||
output += "<"
|
|
||||||
break;
|
|
||||||
case ">":
|
|
||||||
output += ">"
|
|
||||||
break;
|
|
||||||
case "&":
|
|
||||||
output += "&"
|
|
||||||
break;
|
|
||||||
case "\"":
|
|
||||||
output += """
|
|
||||||
break;
|
|
||||||
case "'":
|
|
||||||
output += "'";
|
|
||||||
break;
|
|
||||||
case "/":
|
|
||||||
output += "/";
|
|
||||||
break;
|
|
||||||
case "\n":
|
|
||||||
output += " ";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
var charcode : number = input.charCodeAt(i);
|
|
||||||
if (charcode >= 32 && charcode <= 126)
|
|
||||||
output += input[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MakeModPerms(modperms : Permissions) : number {
|
export function HTMLSanitize(input: string): string {
|
||||||
var perms = 0;
|
var output = '';
|
||||||
if (modperms.restore) perms |= 1;
|
for (var i = 0; i < input.length; i++) {
|
||||||
if (modperms.reboot) perms |= 2;
|
switch (input[i]) {
|
||||||
if (modperms.ban) perms |= 4;
|
case '<':
|
||||||
if (modperms.forcevote) perms |= 8;
|
output += '<';
|
||||||
if (modperms.mute) perms |= 16;
|
break;
|
||||||
if (modperms.kick) perms |= 32;
|
case '>':
|
||||||
if (modperms.bypassturn) perms |= 64;
|
output += '>';
|
||||||
if (modperms.rename) perms |= 128;
|
break;
|
||||||
if (modperms.grabip) perms |= 256;
|
case '&':
|
||||||
if (modperms.xss) perms |= 512;
|
output += '&';
|
||||||
return perms;
|
break;
|
||||||
}
|
case '"':
|
||||||
|
output += '"';
|
||||||
|
break;
|
||||||
|
case "'":
|
||||||
|
output += ''';
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
output += '/';
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
output += ' ';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
var charcode: number = input.charCodeAt(i);
|
||||||
|
if (charcode >= 32 && charcode <= 126) output += input[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MakeModPerms(modperms: Permissions): number {
|
||||||
|
var perms = 0;
|
||||||
|
if (modperms.restore) perms |= 1;
|
||||||
|
if (modperms.reboot) perms |= 2;
|
||||||
|
if (modperms.ban) perms |= 4;
|
||||||
|
if (modperms.forcevote) perms |= 8;
|
||||||
|
if (modperms.mute) perms |= 16;
|
||||||
|
if (modperms.kick) perms |= 32;
|
||||||
|
if (modperms.bypassturn) perms |= 64;
|
||||||
|
if (modperms.rename) perms |= 128;
|
||||||
|
if (modperms.grabip) perms |= 256;
|
||||||
|
if (modperms.xss) perms |= 512;
|
||||||
|
return perms;
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,43 +1,37 @@
|
|||||||
export function decode(string : string) : string[] {
|
export function decode(string: string): string[] {
|
||||||
let pos = -1;
|
let pos = -1;
|
||||||
let sections = [];
|
let sections = [];
|
||||||
|
|
||||||
for(;;) {
|
for (;;) {
|
||||||
let len = string.indexOf('.', pos + 1);
|
let len = string.indexOf('.', pos + 1);
|
||||||
|
|
||||||
if(len === -1)
|
if (len === -1) break;
|
||||||
break;
|
|
||||||
|
|
||||||
pos = parseInt(string.slice(pos + 1, len)) + len + 1;
|
pos = parseInt(string.slice(pos + 1, len)) + len + 1;
|
||||||
|
|
||||||
// don't allow funky protocol length
|
// don't allow funky protocol length
|
||||||
if(pos > string.length)
|
if (pos > string.length) return [];
|
||||||
return [];
|
|
||||||
|
|
||||||
sections.push(string.slice(len + 1, pos));
|
sections.push(string.slice(len + 1, pos));
|
||||||
|
|
||||||
|
const sep = string.slice(pos, pos + 1);
|
||||||
|
|
||||||
const sep = string.slice(pos, pos + 1);
|
if (sep === ',') continue;
|
||||||
|
else if (sep === ';') break;
|
||||||
|
// Invalid data.
|
||||||
|
else return [];
|
||||||
|
}
|
||||||
|
|
||||||
if(sep === ',')
|
return sections;
|
||||||
continue;
|
|
||||||
else if(sep === ';')
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
// Invalid data.
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return sections;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function encode(...string : string[]) : string {
|
export function encode(...string: string[]): string {
|
||||||
let command = '';
|
let command = '';
|
||||||
|
|
||||||
for(var i = 0; i < string.length; i++) {
|
for (var i = 0; i < string.length; i++) {
|
||||||
let current = string[i];
|
let current = string[i];
|
||||||
command += current.toString().length + '.' + current;
|
command += current.toString().length + '.' + current;
|
||||||
command += ( i < string.length - 1 ? ',' : ';');
|
command += i < string.length - 1 ? ',' : ';';
|
||||||
}
|
}
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as toml from 'toml';
|
import * as toml from 'toml';
|
||||||
import IConfig from './IConfig.js';
|
import IConfig from './IConfig.js';
|
||||||
import * as fs from "fs";
|
import * as fs from 'fs';
|
||||||
import WSServer from './WSServer.js';
|
import WSServer from './WSServer.js';
|
||||||
|
|
||||||
import { QemuVM, QemuVmDefinition } from '@cvmts/qemu';
|
import { QemuVM, QemuVmDefinition } from '@cvmts/qemu';
|
||||||
@@ -8,51 +8,50 @@ import { QemuVM, QemuVmDefinition } from '@cvmts/qemu';
|
|||||||
import * as Shared from '@cvmts/shared';
|
import * as Shared from '@cvmts/shared';
|
||||||
import AuthManager from './AuthManager.js';
|
import AuthManager from './AuthManager.js';
|
||||||
|
|
||||||
let logger = new Shared.Logger("CVMTS.Init");
|
let logger = new Shared.Logger('CVMTS.Init');
|
||||||
|
|
||||||
logger.Info("CollabVM Server starting up");
|
logger.Info('CollabVM Server starting up');
|
||||||
|
|
||||||
// Parse the config file
|
// Parse the config file
|
||||||
|
|
||||||
var Config : IConfig;
|
let Config: IConfig;
|
||||||
|
|
||||||
if (!fs.existsSync("config.toml")) {
|
if (!fs.existsSync('config.toml')) {
|
||||||
logger.Error("Fatal error: Config.toml not found. Please copy config.example.toml and fill out fields")
|
logger.Error('Fatal error: Config.toml not found. Please copy config.example.toml and fill out fields');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
var configRaw = fs.readFileSync("config.toml").toString();
|
var configRaw = fs.readFileSync('config.toml').toString();
|
||||||
Config = toml.parse(configRaw);
|
Config = toml.parse(configRaw);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.Error("Fatal error: Failed to read or parse the config file: {0}", (e as Error).message);
|
logger.Error('Fatal error: Failed to read or parse the config file: {0}', (e as Error).message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function start() {
|
async function start() {
|
||||||
// Print a warning if qmpSockDir is set
|
// Print a warning if qmpSockDir is set
|
||||||
// and the host OS is Windows, as this
|
// and the host OS is Windows, as this
|
||||||
// configuration will very likely not work.
|
// configuration will very likely not work.
|
||||||
if(process.platform === "win32" && Config.vm.qmpSockDir) {
|
if (process.platform === 'win32' && Config.vm.qmpSockDir) {
|
||||||
logger.Warning("You appear to have the option 'qmpSockDir' enabled in the config.")
|
logger.Warning("You appear to have the option 'qmpSockDir' enabled in the config.");
|
||||||
logger.Warning("This is not supported on Windows, and you will likely run into issues.");
|
logger.Warning('This is not supported on Windows, and you will likely run into issues.');
|
||||||
logger.Warning("To remove this warning, use the qmpHost and qmpPort options instead.");
|
logger.Warning('To remove this warning, use the qmpHost and qmpPort options instead.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init the auth manager if enabled
|
// Init the auth manager if enabled
|
||||||
let auth = Config.auth.enabled ? new AuthManager(Config.auth.apiEndpoint, Config.auth.secretKey) : null;
|
let auth = Config.auth.enabled ? new AuthManager(Config.auth.apiEndpoint, Config.auth.secretKey) : null;
|
||||||
|
|
||||||
// Fire up the VM
|
// Fire up the VM
|
||||||
let def: QemuVmDefinition = {
|
let def: QemuVmDefinition = {
|
||||||
id: Config.collabvm.node,
|
id: Config.collabvm.node,
|
||||||
command: Config.vm.qemuArgs
|
command: Config.vm.qemuArgs
|
||||||
}
|
};
|
||||||
|
|
||||||
var VM = new QemuVM(def);
|
var VM = new QemuVM(def);
|
||||||
await VM.Start();
|
await VM.Start();
|
||||||
|
|
||||||
// Start up the websocket server
|
// Start up the websocket server
|
||||||
var WS = new WSServer(Config, VM, auth);
|
var WS = new WSServer(Config, VM, auth);
|
||||||
WS.listen();
|
WS.listen();
|
||||||
}
|
}
|
||||||
start();
|
start();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Size, Rect } from "@cvmts/shared";
|
import { Size, Rect } from '@cvmts/shared';
|
||||||
|
|
||||||
export function BatchRects(size: Size, rects: Array<Rect>): Rect {
|
export function BatchRects(size: Size, rects: Array<Rect>): Rect {
|
||||||
var mergedX = size.width;
|
var mergedX = size.width;
|
||||||
@@ -38,4 +38,4 @@ export function BatchRects(size: Size, rects: Array<Rect>): Rect {
|
|||||||
width: mergedWidth,
|
width: mergedWidth,
|
||||||
height: mergedHeight
|
height: mergedHeight
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ const kMaxFailCount = 5;
|
|||||||
// TODO: This should be added to QemuVmDefinition and the below export removed
|
// TODO: This should be added to QemuVmDefinition and the below export removed
|
||||||
let gVMShouldSnapshot = true;
|
let gVMShouldSnapshot = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export function setSnapshot(val: boolean) {
|
export function setSnapshot(val: boolean) {
|
||||||
gVMShouldSnapshot = val;
|
gVMShouldSnapshot = val;
|
||||||
}
|
}
|
||||||
@@ -68,10 +66,9 @@ export class QemuVM extends EventEmitter {
|
|||||||
|
|
||||||
// build additional command line statements to enable qmp/vnc over unix sockets
|
// build additional command line statements to enable qmp/vnc over unix sockets
|
||||||
// FIXME: Still use TCP if on Windows.
|
// FIXME: Still use TCP if on Windows.
|
||||||
if(!this.addedAdditionalArguments) {
|
if (!this.addedAdditionalArguments) {
|
||||||
cmd += ' -no-shutdown';
|
cmd += ' -no-shutdown';
|
||||||
if(gVMShouldSnapshot)
|
if (gVMShouldSnapshot) cmd += ' -snapshot';
|
||||||
cmd += ' -snapshot';
|
|
||||||
cmd += ` -qmp unix:${this.GetQmpPath()},server,wait -vnc unix:${this.GetVncPath()}`;
|
cmd += ` -qmp unix:${this.GetQmpPath()},server,wait -vnc unix:${this.GetVncPath()}`;
|
||||||
this.definition.command = cmd;
|
this.definition.command = cmd;
|
||||||
this.addedAdditionalArguments = true;
|
this.addedAdditionalArguments = true;
|
||||||
@@ -183,7 +180,7 @@ export class QemuVM extends EventEmitter {
|
|||||||
if (self.qmpConnected) {
|
if (self.qmpConnected) {
|
||||||
await self.DisconnectQmp();
|
await self.DisconnectQmp();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.DisconnectDisplay();
|
self.DisconnectDisplay();
|
||||||
|
|
||||||
if (self.state != VMState.Stopping) {
|
if (self.state != VMState.Stopping) {
|
||||||
@@ -275,16 +272,13 @@ export class QemuVM extends EventEmitter {
|
|||||||
|
|
||||||
private async DisconnectQmp() {
|
private async DisconnectQmp() {
|
||||||
if (this.qmpConnected) return;
|
if (this.qmpConnected) return;
|
||||||
if(this.qmpInstance == null)
|
if (this.qmpInstance == null) return;
|
||||||
return;
|
|
||||||
|
|
||||||
this.qmpConnected = false;
|
this.qmpConnected = false;
|
||||||
this.qmpInstance.end();
|
this.qmpInstance.end();
|
||||||
this.qmpInstance = null;
|
this.qmpInstance = null;
|
||||||
try {
|
try {
|
||||||
await unlink(this.GetQmpPath());
|
await unlink(this.GetQmpPath());
|
||||||
} catch(err) {
|
} catch (err) {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export default class QmpClient extends Socket {
|
|||||||
// just rethrow lol
|
// just rethrow lol
|
||||||
//throw err;
|
//throw err;
|
||||||
|
|
||||||
console.log("you have pants: rules,", err);
|
console.log('you have pants: rules,', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.once('data', (data) => {
|
this.once('data', (data) => {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
// TODO: `Object` has a toString(), but we should probably gate that off
|
// TODO: `Object` has a toString(), but we should probably gate that off
|
||||||
/// Interface for things that can be turned into strings
|
/// Interface for things that can be turned into strings
|
||||||
export interface ToStringable {
|
export interface ToStringable {
|
||||||
@@ -6,4 +5,4 @@ export interface ToStringable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A type for strings, or things that can (in a valid manner) be turned into strings
|
/// A type for strings, or things that can (in a valid manner) be turned into strings
|
||||||
export type StringLike = string | ToStringable;
|
export type StringLike = string | ToStringable;
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ export type Size = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Rect = {
|
export type Rect = {
|
||||||
x: number,
|
x: number;
|
||||||
y: number,
|
y: number;
|
||||||
width: number,
|
width: number;
|
||||||
height: number
|
height: number;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user