From d2366df9dbd582cff8e6479ce1f66403e38bca7f Mon Sep 17 00:00:00 2001 From: Mike Sawka Date: Thu, 19 Sep 2024 10:42:53 -0700 Subject: [PATCH] updated ws loading code (#397) --- emain/emain.ts | 3 ++- frontend/app/store/ws.ts | 35 +++++++++++++++++--------------- frontend/app/store/wshrpcutil.ts | 6 +++--- package.json | 2 ++ yarn.lock | 33 ++++++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 20 deletions(-) diff --git a/emain/emain.ts b/emain/emain.ts index 5138cb19a..dbc26ac0e 100644 --- a/emain/emain.ts +++ b/emain/emain.ts @@ -12,6 +12,7 @@ import { sprintf } from "sprintf-js"; import { debounce } from "throttle-debounce"; import * as util from "util"; import winston from "winston"; +import { WebSocket as NodeWebSocket } from "ws"; import { initGlobal } from "../frontend/app/store/global"; import * as services from "../frontend/app/store/services"; import { initElectronWshrpc } from "../frontend/app/store/wshrpcutil"; @@ -861,7 +862,7 @@ async function appMain() { await configureAutoUpdater(); setTimeout(runActiveTimer, 5000); // start active timer, wait 5s just to be safe try { - initElectronWshrpc(ElectronWshClient, AuthKey); + initElectronWshrpc(ElectronWshClient, { authKey: AuthKey, wsImpl: NodeWebSocket }); } catch (e) { console.log("error initializing wshrpc", e); } diff --git a/frontend/app/store/ws.ts b/frontend/app/store/ws.ts index 5062af8f6..120577d4d 100644 --- a/frontend/app/store/ws.ts +++ b/frontend/app/store/ws.ts @@ -3,18 +3,10 @@ import debug from "debug"; import { sprintf } from "sprintf-js"; -import type { WebSocket as ElectronWebSocketType } from "ws"; +import type { WebSocket as NodeWebSocketType } from "ws"; -let ElectronWebSocket: typeof ElectronWebSocketType; const AuthKeyHeader = "X-AuthKey"; -if (typeof window === "undefined") { - try { - const WebSocket = require("ws") as typeof ElectronWebSocketType; - ElectronWebSocket = WebSocket; - } catch (e) {} -} - const dlog = debug("wave:ws"); const WarnWebSocketSendSize = 1024 * 1024; // 1MB @@ -34,8 +26,13 @@ function removeWSReconnectHandler(handler: () => void) { type WSEventCallback = (arg0: WSEventType) => void; +type ElectronOverrideOpts = { + wsImpl: typeof NodeWebSocketType; + authKey: string; +}; + class WSControl { - wsConn: WebSocket | ElectronWebSocketType; + wsConn: WebSocket | NodeWebSocketType; open: boolean; opening: boolean = false; reconnectTimes: number = 0; @@ -47,14 +44,19 @@ class WSControl { wsLog: string[] = []; baseHostPort: string; lastReconnectTime: number = 0; - authKey: string = null; // used only by electron + eoOpts: ElectronOverrideOpts; - constructor(baseHostPort: string, windowId: string, messageCallback: WSEventCallback, authKey?: string) { + constructor( + baseHostPort: string, + windowId: string, + messageCallback: WSEventCallback, + electronOverrideOpts?: ElectronOverrideOpts + ) { this.baseHostPort = baseHostPort; this.messageCallback = messageCallback; this.windowId = windowId; this.open = false; - this.authKey = authKey; + this.eoOpts = electronOverrideOpts; setInterval(this.sendPing.bind(this), 5000); } @@ -65,9 +67,9 @@ class WSControl { this.lastReconnectTime = Date.now(); dlog("try reconnect:", desc); this.opening = true; - if (ElectronWebSocket) { - this.wsConn = new ElectronWebSocket(this.baseHostPort + "/ws?windowid=" + this.windowId, { - headers: { [AuthKeyHeader]: this.authKey }, + if (this.eoOpts) { + this.wsConn = new this.eoOpts.wsImpl(this.baseHostPort + "/ws?windowid=" + this.windowId, { + headers: { [AuthKeyHeader]: this.eoOpts.authKey }, }); } else { this.wsConn = new WebSocket(this.baseHostPort + "/ws?windowid=" + this.windowId); @@ -208,3 +210,4 @@ class WSControl { } export { addWSReconnectHandler, removeWSReconnectHandler, WSControl }; +export type { ElectronOverrideOpts }; diff --git a/frontend/app/store/wshrpcutil.ts b/frontend/app/store/wshrpcutil.ts index 1f5c1c797..69c4bac73 100644 --- a/frontend/app/store/wshrpcutil.ts +++ b/frontend/app/store/wshrpcutil.ts @@ -5,7 +5,7 @@ import { wpsReconnectHandler } from "@/app/store/wps"; import { WshClient } from "@/app/store/wshclient"; import { makeWindowRouteId, WshRouter } from "@/app/store/wshrouter"; import { getWSServerEndpoint } from "@/util/endpoints"; -import { addWSReconnectHandler, WSControl } from "./ws"; +import { addWSReconnectHandler, ElectronOverrideOpts, WSControl } from "./ws"; let globalWS: WSControl; let DefaultRouter: WshRouter; @@ -114,12 +114,12 @@ if (globalThis.window != null) { globalThis["consumeGenerator"] = consumeGenerator; } -function initElectronWshrpc(electronClient: WshClient, authKey: string) { +function initElectronWshrpc(electronClient: WshClient, eoOpts: ElectronOverrideOpts) { DefaultRouter = new WshRouter(new UpstreamWshRpcProxy()); const handleFn = (event: WSEventType) => { DefaultRouter.recvRpcMessage(event.data); }; - globalWS = new WSControl(getWSServerEndpoint(), "electron", handleFn, authKey); + globalWS = new WSControl(getWSServerEndpoint(), "electron", handleFn, eoOpts); globalWS.connectNow("connectWshrpc"); DefaultRouter.registerRoute(electronClient.routeId, electronClient); addWSReconnectHandler(() => { diff --git a/package.json b/package.json index e57c1097f..855071128 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,7 @@ "@xterm/addon-webgl": "^0.18.0", "@xterm/xterm": "^5.5.0", "base64-js": "^1.5.1", + "bufferutil": "^4.0.8", "clsx": "^2.1.1", "color": "^4.2.3", "css-tree": "^3.0.0", @@ -128,6 +129,7 @@ "throttle-debounce": "^5.0.2", "tinycolor2": "^1.6.0", "use-device-pixel-ratio": "^1.1.2", + "utf-8-validate": "^6.0.4", "winston": "^3.14.2", "ws": "^8.18.0" }, diff --git a/yarn.lock b/yarn.lock index 9bc8a1fbe..ff58aebf6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3467,6 +3467,16 @@ __metadata: languageName: node linkType: hard +"bufferutil@npm:^4.0.8": + version: 4.0.8 + resolution: "bufferutil@npm:4.0.8" + dependencies: + node-gyp: "npm:latest" + node-gyp-build: "npm:^4.3.0" + checksum: 10c0/36cdc5b53a38d9f61f89fdbe62029a2ebcd020599862253fefebe31566155726df9ff961f41b8c97b02b4c12b391ef97faf94e2383392654cf8f0ed68f76e47c + languageName: node + linkType: hard + "builder-util-runtime@npm:9.2.5": version: 9.2.5 resolution: "builder-util-runtime@npm:9.2.5" @@ -8276,6 +8286,17 @@ __metadata: languageName: node linkType: hard +"node-gyp-build@npm:^4.3.0": + version: 4.8.2 + resolution: "node-gyp-build@npm:4.8.2" + bin: + node-gyp-build: bin.js + node-gyp-build-optional: optional.js + node-gyp-build-test: build-test.js + checksum: 10c0/d816b43974d31d6257b6e87d843f2626c72389a285208394bc57a7766b210454d2642860a5e5b5c333d8ecabaeabad3b31b94f58cf8ca1aabdef0c320d02baaa + languageName: node + linkType: hard + "node-gyp@npm:^9.0.0": version: 9.4.1 resolution: "node-gyp@npm:9.4.1" @@ -10228,6 +10249,7 @@ __metadata: "@xterm/addon-webgl": "npm:^0.18.0" "@xterm/xterm": "npm:^5.5.0" base64-js: "npm:^1.5.1" + bufferutil: "npm:^4.0.8" clsx: "npm:^2.1.1" color: "npm:^4.2.3" css-tree: "npm:^3.0.0" @@ -10280,6 +10302,7 @@ __metadata: typescript: "npm:^5.6.2" typescript-eslint: "npm:^8.5.0" use-device-pixel-ratio: "npm:^1.1.2" + utf-8-validate: "npm:^6.0.4" vite: "npm:^5.4.6" vite-plugin-image-optimizer: "npm:^1.1.8" vite-plugin-static-copy: "npm:^1.0.6" @@ -10810,6 +10833,16 @@ __metadata: languageName: node linkType: hard +"utf-8-validate@npm:^6.0.4": + version: 6.0.4 + resolution: "utf-8-validate@npm:6.0.4" + dependencies: + node-gyp: "npm:latest" + node-gyp-build: "npm:^4.3.0" + checksum: 10c0/f7042d94aec6ca02461b64e725bdc7262266610dbb787331e5bbd49374ef6f75fe9900600df3fc63d97906c23614a965c8989b4bf95d70bf35dc617da99215e7 + languageName: node + linkType: hard + "utf8-byte-length@npm:^1.0.1": version: 1.0.5 resolution: "utf8-byte-length@npm:1.0.5"