From c7454c13cc8da06f5520e5ca2141e1233dd6dce2 Mon Sep 17 00:00:00 2001 From: Khairul Hidayat Date: Mon, 18 Mar 2024 03:01:39 +0700 Subject: [PATCH] feat: start vnc server if not started yet --- backend/.env.example | 1 + backend/lib/vnc.ts | 38 ++++++++++++++++++++++++++++++++++++++ backend/websocket.ts | 6 ++---- 3 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 backend/lib/vnc.ts diff --git a/backend/.env.example b/backend/.env.example index 3792cb7..da4364e 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -9,3 +9,4 @@ PC_MAC_ADDR= TERMINAL_SHELL= FILE_DIRS="/some/path;/another/path" VNC_PORT=5901 +VNC_START_CMD=vncserver :1 diff --git a/backend/lib/vnc.ts b/backend/lib/vnc.ts new file mode 100644 index 0000000..b864a1d --- /dev/null +++ b/backend/lib/vnc.ts @@ -0,0 +1,38 @@ +import type { WebSocket } from "ws"; +import { websockify } from "./websockify"; +import net from "node:net"; +import { spawn } from "node:child_process"; + +const VNC_PORT = parseInt(process.env.VNC_PORT || "") || 5901; +const VNC_START_CMD = process.env.VNC_START_CMD; + +export const createVNCSession = async (ws: WebSocket) => { + const isVncStarted = await isPortOpen(VNC_PORT); + + // VNC is not started, start it. + if (!isVncStarted && VNC_START_CMD) { + const cmd = VNC_START_CMD.split(" "); + const child = spawn(cmd[0], cmd.slice(1)); + + await new Promise((resolve) => { + child.on("close", () => resolve(null)); + }); + } + + websockify(ws, "localhost", VNC_PORT); +}; + +async function isPortOpen(port: number) { + return new Promise((resolve) => { + const tester = net + .createServer() + .once("error", function (err: any) { + resolve(err.code === "EADDRINUSE"); + }) + .once("listening", function () { + tester.close(); + resolve(false); + }) + .listen(port); + }); +} diff --git a/backend/websocket.ts b/backend/websocket.ts index 04d8d5c..4e48232 100644 --- a/backend/websocket.ts +++ b/backend/websocket.ts @@ -1,9 +1,7 @@ import { WebSocketServer } from "ws"; import { verifyToken } from "./lib/jwt"; import { createTerminalSession } from "./lib/terminal"; -import { websockify } from "./lib/websockify"; - -const VNC_PORT = parseInt(process.env.VNC_PORT || "") || 5901; +import { createVNCSession } from "./lib/vnc"; const createWsServer = (server: any) => { const wss = new WebSocketServer({ server: server as never }); @@ -25,7 +23,7 @@ const createWsServer = (server: any) => { } if (url.pathname === "/vnc") { - websockify(ws, "localhost", VNC_PORT); + createVNCSession(ws); } ws.on("error", console.error);