re-implement binrect protocol

pretty easy since we can just subclass guac
This commit is contained in:
modeco80
2024-08-21 22:18:11 -04:00
parent 6e1a075194
commit 4583531fce
5 changed files with 69 additions and 18 deletions

View File

@@ -1,6 +1,16 @@
import * as msgpack from 'msgpackr'; import * as msgpack from 'msgpackr';
import { CollabVMProtocolMessage, CollabVMProtocolMessageType } from '@cvmts/collab-vm-1.2-binary-protocol'; import { CollabVMProtocolMessage, CollabVMProtocolMessageType } from '@cvmts/collab-vm-1.2-binary-protocol';
import { GuacamoleProtocol } from './GuacamoleProtocol.js';
// TODO: reimplement binrects protocol import { ScreenRect } from './Protocol';
// we can just create/proxy a GuacamoleProtocol manually,
// and for the rects do our own thing export class BinRectsProtocol extends GuacamoleProtocol {
sendScreenUpdate(rect: ScreenRect): void {
let bmsg: CollabVMProtocolMessage = {
type: CollabVMProtocolMessageType.rect,
rect: rect
};
this.user?.socket.sendBinary(msgpack.encode(bmsg));
}
}

View File

@@ -211,6 +211,8 @@ export default class CollabVMServer implements IProtocolHandlers {
this.clients.splice(clientIndex, 1); this.clients.splice(clientIndex, 1);
user.protocol.dispose();
this.logger.info(`Disconnect From ${user.IP.address}${user.username ? ` with username ${user.username}` : ''}`); this.logger.info(`Disconnect From ${user.IP.address}${user.username ? ` with username ${user.username}` : ''}`);
if (!user.username) return; if (!user.username) return;
if (this.TurnQueue.toArray().indexOf(user) !== -1) { if (this.TurnQueue.toArray().indexOf(user) !== -1) {
@@ -273,9 +275,9 @@ export default class CollabVMServer implements IProtocolHandlers {
// Set rank // Set rank
user.rank = res.rank; user.rank = res.rank;
if (user.rank === Rank.Admin) { if (user.rank === Rank.Admin) {
user.sendMsg(cvm.guacEncode('admin', '0', '1')); user.protocol.sendAdminLoginResponse(true, undefined);
} else if (user.rank === Rank.Moderator) { } else if (user.rank === Rank.Moderator) {
user.sendMsg(cvm.guacEncode('admin', '0', '3', this.ModPerms.toString())); user.protocol.sendAdminLoginResponse(true, this.ModPerms);
} }
this.clients.forEach((c) => c.sendMsg(cvm.guacEncode('adduser', '1', user.username!, user.rank.toString()))); this.clients.forEach((c) => c.sendMsg(cvm.guacEncode('adduser', '1', user.username!, user.rank.toString())));
} else { } else {
@@ -303,12 +305,11 @@ export default class CollabVMServer implements IProtocolHandlers {
for (let cap of capability) { for (let cap of capability) {
switch (cap) { switch (cap) {
// binary 1.0 (msgpack rects) // binary 1.0 (msgpack rects)
// TODO: re-enable once binary1.0 is enabled
case 'bin': case 'bin':
this.logger.info('Binary 1.0 protocol is currently disabled for refactoring'); user.Capabilities.bin = true;
//user.Capabilities.bin = true; user.protocol.dispose();
//user.protocol = TheProtocolManager.createProtocol('binary1', user); user.protocol = TheProtocolManager.createProtocol('binary1', user);
//user.protocol.setHandler(this as IProtocolHandlers); user.protocol.setHandler(this as IProtocolHandlers);
break; break;
default: default:
break; break;
@@ -513,12 +514,12 @@ export default class CollabVMServer implements IProtocolHandlers {
if (pwdHash === this.Config.collabvm.adminpass) { if (pwdHash === this.Config.collabvm.adminpass) {
user.rank = Rank.Admin; user.rank = Rank.Admin;
user.sendMsg(cvm.guacEncode('admin', '0', '1')); user.protocol.sendAdminLoginResponse(true, undefined);
} else if (this.Config.collabvm.moderatorEnabled && pwdHash === this.Config.collabvm.modpass) { } else if (this.Config.collabvm.moderatorEnabled && pwdHash === this.Config.collabvm.modpass) {
user.rank = Rank.Moderator; user.rank = Rank.Moderator;
user.sendMsg(cvm.guacEncode('admin', '0', '3', this.ModPerms.toString())); user.protocol.sendAdminLoginResponse(true, this.ModPerms);
} else { } else {
user.sendMsg(cvm.guacEncode('admin', '0', '0')); user.protocol.sendAdminLoginResponse(false, undefined);
return; return;
} }
@@ -526,14 +527,22 @@ export default class CollabVMServer implements IProtocolHandlers {
await this.SendFullScreenWithSize(user); await this.SendFullScreenWithSize(user);
} }
this.clients.forEach((c) => c.sendMsg(cvm.guacEncode('adduser', '1', user.username!, user.rank.toString()))); // Update rank
this.clients.forEach((c) =>
c.protocol.sendAddUser([
{
username: user.username!,
rank: user.rank
}
])
);
} }
async onAdminMonitor(user: User, node: string, command: string) { async onAdminMonitor(user: User, node: string, command: string) {
if (user.rank !== Rank.Admin) return; if (user.rank !== Rank.Admin) return;
if (node !== this.Config.collabvm.node) return; if (node !== this.Config.collabvm.node) return;
let output = await this.VM.MonitorCommand(command); let output = await this.VM.MonitorCommand(command);
user.sendMsg(cvm.guacEncode('admin', '2', String(output))); user.protocol.sendAdminMonitorResponse(String(output));
} }
onAdminRestore(user: User, node: string): void { onAdminRestore(user: User, node: string): void {
@@ -605,7 +614,7 @@ export default class CollabVMServer implements IProtocolHandlers {
if (user.rank !== Rank.Admin && (user.rank !== Rank.Moderator || !this.Config.collabvm.moderatorPermissions.grabip)) return; if (user.rank !== Rank.Admin && (user.rank !== Rank.Moderator || !this.Config.collabvm.moderatorPermissions.grabip)) return;
let target = this.clients.find((c) => c.username === username); let target = this.clients.find((c) => c.username === username);
if (!target) return; if (!target) return;
user.sendMsg(cvm.guacEncode('admin', '19', username, target.IP.address)); user.protocol.sendAdminIPResponse(username, target.IP.address);
} }
onAdminBypassTurn(user: User): void { onAdminBypassTurn(user: User): void {

View File

@@ -11,12 +11,17 @@ export class GuacamoleProtocol implements IProtocol {
name: 'CVMTS.GuacamoleProtocol' name: 'CVMTS.GuacamoleProtocol'
}); });
private user: User | null = null; protected user: User | null = null;
init(u: User): void { init(u: User): void {
this.user = u; this.user = u;
} }
dispose(): void {
this.user = null;
this.handlers = null;
}
setHandler(handlers: IProtocolHandlers): void { setHandler(handlers: IProtocolHandlers): void {
this.handlers = handlers; this.handlers = handlers;
} }
@@ -237,6 +242,26 @@ export class GuacamoleProtocol implements IProtocol {
} }
} }
sendAdminLoginResponse(ok: boolean, modPerms: number | undefined): void {
if (ok) {
if (modPerms == undefined) {
this.user?.sendMsg(cvm.guacEncode('admin', '0', '1'));
} else {
this.user?.sendMsg(cvm.guacEncode('admin', '0', '3', modPerms.toString()));
}
} else {
this.user?.sendMsg(cvm.guacEncode('admin', '0', '0'));
}
}
sendAdminMonitorResponse(output: string): void {
this.user?.sendMsg(cvm.guacEncode('admin', '2', output));
}
sendAdminIPResponse(username: string, ip: string): void {
this.user?.sendMsg(cvm.guacEncode('admin', '19', username, ip));
}
sendChatMessage(username: string, message: string): void { sendChatMessage(username: string, message: string): void {
this.user?.sendMsg(cvm.guacEncode('chat', username, message)); this.user?.sendMsg(cvm.guacEncode('chat', username, message));
} }

View File

@@ -77,6 +77,7 @@ export interface IProtocolHandlers {
// Abstracts away all of the CollabVM protocol details // Abstracts away all of the CollabVM protocol details
export interface IProtocol { export interface IProtocol {
init(u: User): void; init(u: User): void;
dispose(): void;
// Sets handler object. // Sets handler object.
setHandler(handlers: IProtocolHandlers): void; setHandler(handlers: IProtocolHandlers): void;
@@ -98,6 +99,10 @@ export interface IProtocol {
sendLoginResponse(ok: boolean, message: string | undefined): void; sendLoginResponse(ok: boolean, message: string | undefined): void;
sendAdminLoginResponse(ok: boolean, modPerms: number | undefined): void;
sendAdminMonitorResponse(output: string): void;
sendAdminIPResponse(username: string, ip: string): void;
sendChatMessage(username: '' | string, message: string): void; sendChatMessage(username: '' | string, message: string): void;
sendChatHistoryMessage(history: ProtocolChatHistory[]): void; sendChatHistoryMessage(history: ProtocolChatHistory[]): void;

View File

@@ -18,6 +18,7 @@ import { BanManager } from './BanManager.js';
import { QemuVMShim } from './vm/qemu.js'; import { QemuVMShim } from './vm/qemu.js';
import { TheProtocolManager } from './Protocol.js'; import { TheProtocolManager } from './Protocol.js';
import { GuacamoleProtocol } from './GuacamoleProtocol.js'; import { GuacamoleProtocol } from './GuacamoleProtocol.js';
import { BinRectsProtocol } from './BinRectsProtocol.js';
let logger = pino(); let logger = pino();
@@ -99,8 +100,9 @@ async function start() {
process.on('SIGINT', async () => await stop()); process.on('SIGINT', async () => await stop());
process.on('SIGTERM', async () => await stop()); process.on('SIGTERM', async () => await stop());
// Register protocol(s) // Register protocol(s) that the server supports
TheProtocolManager.registerProtocol("guacamole", () => new GuacamoleProtocol); TheProtocolManager.registerProtocol("guacamole", () => new GuacamoleProtocol);
TheProtocolManager.registerProtocol("binary1", () => new BinRectsProtocol);
await VM.Start(); await VM.Start();
// Start up the server // Start up the server