From 418fc55112b079add249395442aa4cdac688f928 Mon Sep 17 00:00:00 2001 From: hensm Date: Mon, 25 Apr 2022 10:17:59 +0100 Subject: [PATCH] Clean up app message handling a little --- app/package-lock.json | 14 +++++- app/package.json | 1 + app/src/bridge/components/cast/Session.ts | 12 ++--- app/src/bridge/components/cast/index.ts | 20 ++++---- app/src/bridge/components/discovery.ts | 13 +++--- app/src/bridge/components/mediaServer.ts | 16 +++---- app/src/bridge/index.ts | 7 ++- app/src/bridge/lib/nativeMessaging.ts | 14 ------ app/src/bridge/messaging.ts | 46 ++++++++++++++++++- .../bridge/{types.ts => messagingTypes.ts} | 0 app/src/daemon.ts | 1 - 11 files changed, 91 insertions(+), 53 deletions(-) delete mode 100644 app/src/bridge/lib/nativeMessaging.ts rename app/src/bridge/{types.ts => messagingTypes.ts} (100%) diff --git a/app/package-lock.json b/app/package-lock.json index b5c4f6c..98828c7 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -15,7 +15,6 @@ "mime-types": "^2.1.34", "minimist": "^1.2.5", "node-fetch": "^3.2.2", - "rage-edit": "*", "tweetnacl": "^1.0.3", "ws": "^8.5.0" }, @@ -27,6 +26,7 @@ "fs-extra": "^10.0.1", "mustache": "^4.2.0", "pkg": "^5.5.2", + "tiny-typed-emitter": "^2.1.0", "typescript": "^4.6.2" }, "optionalDependencies": { @@ -1888,6 +1888,12 @@ "node": ">= 6" } }, + "node_modules/tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==", + "dev": true + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -3584,6 +3590,12 @@ } } }, + "tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", diff --git a/app/package.json b/app/package.json index 75c8c3c..5adc446 100644 --- a/app/package.json +++ b/app/package.json @@ -31,6 +31,7 @@ "fs-extra": "^10.0.1", "mustache": "^4.2.0", "pkg": "^5.5.2", + "tiny-typed-emitter": "^2.1.0", "typescript": "^4.6.2" }, "optionalDependencies": { diff --git a/app/src/bridge/components/cast/Session.ts b/app/src/bridge/components/cast/Session.ts index bdfc9c1..b18defa 100644 --- a/app/src/bridge/components/cast/Session.ts +++ b/app/src/bridge/components/cast/Session.ts @@ -2,9 +2,9 @@ import { Channel } from "castv2"; -import { sendMessage } from "../../lib/nativeMessaging"; +import messaging from "../../messaging"; -import { ReceiverDevice } from "../../types"; +import { ReceiverDevice } from "../../messagingTypes"; import { ReceiverMessage } from "./types"; import CastClient, { NS_CONNECTION, NS_HEARTBEAT } from "./client"; @@ -74,7 +74,7 @@ export default class Session extends CastClient { const { friendlyName } = this.receiverDevice; - sendMessage({ + messaging.sendMessage({ subject: "cast:sessionCreated", data: { sessionId: this.sessionId, @@ -104,7 +104,7 @@ export default class Session extends CastClient { break; } - sendMessage({ + messaging.sendMessage({ subject: "cast:sessionUpdated", data: { sessionId: this.sessionId, @@ -141,7 +141,7 @@ export default class Session extends CastClient { messageData = JSON.stringify(messageData); - sendMessage({ + messaging.sendMessage({ subject: "cast:receivedSessionMessage", data: { sessionId: this.sessionId, @@ -187,7 +187,7 @@ export default class Session extends CastClient { // Handle client connection closed this.client.on("close", () => { if (this.sessionId) { - sendMessage({ + messaging.sendMessage({ subject: "cast:sessionStopped", data: { sessionId: this.sessionId } }); diff --git a/app/src/bridge/components/cast/index.ts b/app/src/bridge/components/cast/index.ts index e6f3b04..bbad39c 100644 --- a/app/src/bridge/components/cast/index.ts +++ b/app/src/bridge/components/cast/index.ts @@ -1,14 +1,10 @@ "use strict"; -import castv2 from "castv2"; - -import { sendMessage } from "../../lib/nativeMessaging"; -import { Message } from "../../messaging"; +import messaging, { Message } from "../../messaging"; import Session from "./Session"; import CastClient, { NS_CONNECTION, NS_RECEIVER } from "./client"; - const sessions = new Map(); export function handleCastMessage(message: Message) { @@ -29,7 +25,7 @@ export function handleCastMessage(message: Message) { const session = sessions.get(sessionId); if (!session) { - sendMessage({ + messaging.sendMessage({ subject: "cast:impl_sendMessage", data: { error: "Session does not exist", @@ -44,7 +40,7 @@ export function handleCastMessage(message: Message) { try { session.sendReceiverMessage(messageData); } catch (err) { - sendMessage({ + messaging.sendMessage({ subject: "cast:impl_sendMessage", data: { error: `Failed to send message (${err})`, @@ -57,7 +53,7 @@ export function handleCastMessage(message: Message) { } // Success - sendMessage({ + messaging.sendMessage({ subject: "cast:impl_sendMessage", data: { sessionId, messageId } }); @@ -70,7 +66,7 @@ export function handleCastMessage(message: Message) { const session = sessions.get(sessionId); if (!session) { - sendMessage({ + messaging.sendMessage({ subject: "cast:impl_sendMessage", data: { error: "Session does not exist", @@ -91,7 +87,7 @@ export function handleCastMessage(message: Message) { session.sendMessage(namespace, messageData); } catch (err) { - sendMessage({ + messaging.sendMessage({ subject: "cast:impl_sendMessage", data: { error: `Failed to send message (${err})`, @@ -104,7 +100,7 @@ export function handleCastMessage(message: Message) { } // Success - sendMessage({ + messaging.sendMessage({ subject: "cast:impl_sendMessage", data: { sessionId, messageId } }); @@ -116,7 +112,7 @@ export function handleCastMessage(message: Message) { const { receiverDevice } = message.data; const client = new CastClient(); - client.connect(receiverDevice.host). then(() => { + client.connect(receiverDevice.host).then(() => { (client.sendReceiverMessage as any)({ type: "STOP" }); }); diff --git a/app/src/bridge/components/discovery.ts b/app/src/bridge/components/discovery.ts index b69c274..17e8165 100644 --- a/app/src/bridge/components/discovery.ts +++ b/app/src/bridge/components/discovery.ts @@ -2,9 +2,10 @@ import mdns from "mdns"; +import messaging from "../messaging"; +import { ReceiverDevice } from "../messagingTypes"; + import Remote from "./cast/remote"; -import { ReceiverDevice } from "../types"; -import { sendMessage } from "../lib/nativeMessaging"; /** * Chromecast TXT record @@ -80,7 +81,7 @@ browser.on("serviceUp", service => { port: service.port }; - sendMessage({ + messaging.sendMessage({ subject: "main:receiverDeviceUp", data: { deviceId: device.id, @@ -94,7 +95,7 @@ browser.on("serviceUp", service => { new Remote(device.host, { // RECEIVER_STATUS onReceiverStatusUpdate(status) { - sendMessage({ + messaging.sendMessage({ subject: "main:receiverDeviceStatusUpdated", data: { deviceId: device.id, status } }); @@ -103,7 +104,7 @@ browser.on("serviceUp", service => { onMediaStatusUpdate(status) { if (!status) return; - sendMessage({ + messaging.sendMessage({ subject: "main:receiverDeviceMediaStatusUpdated", data: { deviceId: device.id, status } }); @@ -121,7 +122,7 @@ browser.on("serviceDown", service => { // Filter invalid results if (!service.name) return; - sendMessage({ + messaging.sendMessage({ subject: "main:receiverDeviceDown", data: { deviceId: service.name } }); diff --git a/app/src/bridge/components/mediaServer.ts b/app/src/bridge/components/mediaServer.ts index 900c7b2..ff5e312 100644 --- a/app/src/bridge/components/mediaServer.ts +++ b/app/src/bridge/components/mediaServer.ts @@ -8,7 +8,7 @@ import stream from "stream"; import mime from "mime-types"; -import { sendMessage } from "../lib/nativeMessaging"; +import messaging from "../messaging"; import { convertSrtToVtt } from "../lib/subtitles"; export let mediaServer: http.Server | undefined; @@ -30,7 +30,7 @@ export async function startMediaServer(filePath: string, port: number) { fileName = path.basename(filePath); fileSize = stat.size; } else { - sendMessage({ + messaging.sendMessage({ subject: "mediaCast:mediaServerError", data: "Media path is not a file." }); @@ -38,7 +38,7 @@ export async function startMediaServer(filePath: string, port: number) { return; } } catch (err) { - sendMessage({ + messaging.sendMessage({ subject: "mediaCast:mediaServerError", data: "Failed to find media path." }); @@ -48,7 +48,7 @@ export async function startMediaServer(filePath: string, port: number) { const contentType = mime.lookup(filePath); if (!contentType) { - sendMessage({ + messaging.sendMessage({ subject: "mediaCast:mediaServerError", data: "Failed to find media type." }); @@ -137,12 +137,12 @@ export async function startMediaServer(filePath: string, port: number) { }); mediaServer.on("close", () => { - sendMessage({ + messaging.sendMessage({ subject: "mediaCast:mediaServerStopped" }); }); mediaServer.on("error", err => { - sendMessage({ + messaging.sendMessage({ subject: "mediaCast:mediaServerError", data: err.message }); @@ -160,7 +160,7 @@ export async function startMediaServer(filePath: string, port: number) { } if (!localAddresses.length) { - sendMessage({ + messaging.sendMessage({ subject: "mediaCast:mediaServerError", data: "Failed to get local address." }); @@ -168,7 +168,7 @@ export async function startMediaServer(filePath: string, port: number) { return; } - sendMessage({ + messaging.sendMessage({ subject: "mediaCast:mediaServerStarted", data: { mediaPath: fileName, diff --git a/app/src/bridge/index.ts b/app/src/bridge/index.ts index 7d9f1ea..15bf13a 100755 --- a/app/src/bridge/index.ts +++ b/app/src/bridge/index.ts @@ -1,7 +1,6 @@ "use strict"; -import { decodeTransform, encodeTransform } from "./lib/nativeMessaging"; -import { Message } from "./messaging"; +import messaging, { Message } from "./messaging"; import { handleCastMessage } from "./components/cast"; import { startDiscovery, stopDiscovery } from "./components/discovery"; @@ -21,11 +20,11 @@ process.on("SIGTERM", () => { * Initializes the counterpart objects and is responsible * for managing existing ones. */ -decodeTransform.on("data", (message: Message) => { +messaging.on("message", (message: Message) => { switch (message.subject) { case "bridge:getInfo": case "bridge:/getInfo": { - encodeTransform.write(__applicationVersion); + messaging.send(__applicationVersion); break; } diff --git a/app/src/bridge/lib/nativeMessaging.ts b/app/src/bridge/lib/nativeMessaging.ts deleted file mode 100644 index d0ed148..0000000 --- a/app/src/bridge/lib/nativeMessaging.ts +++ /dev/null @@ -1,14 +0,0 @@ -"use strict"; - -import { DecodeTransform, EncodeTransform } from "../../transforms"; -import { Message } from "../messaging"; - -export const decodeTransform = new DecodeTransform(); -export const encodeTransform = new EncodeTransform(); - -process.stdin.pipe(decodeTransform); -encodeTransform.pipe(process.stdout); - -export function sendMessage(message: Message) { - encodeTransform.write(message); -} diff --git a/app/src/bridge/messaging.ts b/app/src/bridge/messaging.ts index 2d504cc..610a706 100644 --- a/app/src/bridge/messaging.ts +++ b/app/src/bridge/messaging.ts @@ -1,5 +1,9 @@ "use strict"; +import { TypedEmitter } from "tiny-typed-emitter"; + +import { DecodeTransform, EncodeTransform } from "../transforms"; + import { MediaStatus, ReceiverStatus, @@ -10,7 +14,7 @@ import { ReceiverDevice, CastSessionCreatedDetails, CastSessionUpdatedDetails -} from "./types"; +} from "./messagingTypes"; /** * IMPORTANT: @@ -193,3 +197,43 @@ type NarrowedMessage> = : never; export type Message = NarrowedMessage; + +interface MessengerEvents { + message: (message: Message) => void; +} + +class Messenger extends TypedEmitter { + // Native messaging transforms + private decodeTransform = new DecodeTransform(); + private encodeTransform = new EncodeTransform(); + + constructor() { + super(); + + // Hook up stdin -> stdout + process.stdin.pipe(this.decodeTransform); + this.encodeTransform.pipe(process.stdout); + + this.decodeTransform.on("error", err => + console.error("err (message decode):", err) + ); + this.encodeTransform.on("error", err => + console.error("err (message encode):", err) + ); + + this.decodeTransform.on("data", (message: Message) => { + this.emit("message", message); + }); + } + + /** Sends a message to the extension. */ + sendMessage(message: Message) { + this.encodeTransform.write(message); + } + + send(data: any) { + this.encodeTransform.write(data); + } +} + +export default new Messenger(); diff --git a/app/src/bridge/types.ts b/app/src/bridge/messagingTypes.ts similarity index 100% rename from app/src/bridge/types.ts rename to app/src/bridge/messagingTypes.ts diff --git a/app/src/daemon.ts b/app/src/daemon.ts index 796e3c2..ff8aa52 100644 --- a/app/src/daemon.ts +++ b/app/src/daemon.ts @@ -3,7 +3,6 @@ import { spawn } from "child_process"; import { Readable } from "stream"; -import minimist from "minimist"; import WebSocket from "ws"; import { DecodeTransform, EncodeTransform } from "./transforms";