diff --git a/plugins/core/package.json b/plugins/core/package.json index ecf8e92df..7d60b9bc0 100644 --- a/plugins/core/package.json +++ b/plugins/core/package.json @@ -28,7 +28,6 @@ "interfaces": [ "@scrypted/launcher-ignore", "HttpRequestHandler", - "EngineIOHandler", "DeviceProvider", "SystemSettings", "Settings" diff --git a/plugins/core/src/main.ts b/plugins/core/src/main.ts index 2287bb3c1..95f6cf858 100644 --- a/plugins/core/src/main.ts +++ b/plugins/core/src/main.ts @@ -12,7 +12,7 @@ import { MediaCore } from './media-core'; import { newScript, ScriptCore, ScriptCoreNativeId } from './script-core'; import { TerminalService, TerminalServiceNativeId } from './terminal-service'; import { UsersCore, UsersNativeId } from './user'; -import { ReplService, ReplServiceNativeId } from './repl-service'; +import { ConsoleServiceNativeId, PluginSocketService, ReplServiceNativeId } from './plugin-socket-service'; const { systemManager, deviceManager, endpointManager } = sdk; @@ -31,7 +31,7 @@ interface RoutedHttpRequest extends HttpRequest { params: { [key: string]: string }; } -class ScryptedCore extends ScryptedDeviceBase implements HttpRequestHandler, EngineIOHandler, DeviceProvider, Settings { +class ScryptedCore extends ScryptedDeviceBase implements HttpRequestHandler, DeviceProvider, Settings { router: any = Router(); publicRouter: any = Router(); mediaCore: MediaCore; @@ -39,7 +39,8 @@ class ScryptedCore extends ScryptedDeviceBase implements HttpRequestHandler, Eng aggregateCore: AggregateCore; automationCore: AutomationCore; users: UsersCore; - replService: ReplService; + consoleService: PluginSocketService; + replService: PluginSocketService; terminalService: TerminalService; localAddresses: string[]; storageSettings = new StorageSettings(this, { @@ -185,7 +186,9 @@ class ScryptedCore extends ScryptedDeviceBase implements HttpRequestHandler, Eng if (nativeId === TerminalServiceNativeId) return this.terminalService ||= new TerminalService(); if (nativeId === ReplServiceNativeId) - return this.replService ||= new ReplService(); + return this.replService ||= new PluginSocketService(ReplServiceNativeId, 'repl'); + if (nativeId === ConsoleServiceNativeId) + return this.consoleService ||= new PluginSocketService(ConsoleServiceNativeId, 'console'); } async releaseDevice(id: string, nativeId: string): Promise { @@ -198,35 +201,6 @@ class ScryptedCore extends ScryptedDeviceBase implements HttpRequestHandler, Eng return check; } - async checkService(request: HttpRequest, ws: WebSocket, name: string): Promise { - // only allow admin users to access these services. - if (request.aclId) - return false; - const check = this.checkEngineIoEndpoint(request, name); - if (!check) - return false; - const deviceId = request.url.substr(check.length).split('/')[0]; - const plugins = await systemManager.getComponent('plugins'); - const { nativeId, pluginId } = await plugins.getDeviceInfo(deviceId); - const port = await plugins.getRemoteServicePort(pluginId, name); - const socket = net.connect(port); - socket.on('close', () => ws.close()); - socket.on('data', data => ws.send(data)); - socket.resume(); - socket.write(nativeId?.toString() || 'undefined'); - ws.onclose = () => socket.destroy(); - ws.onmessage = message => socket.write(message.data); - return true; - } - - async onConnection(request: HttpRequest, ws: WebSocket): Promise { - if (await this.checkService(request, ws, 'console')) { - return; - } - - ws.close(); - } - async handlePublicFinal(request: HttpRequest, response: HttpResponse) { // need to strip off the query. const incomingPathname = request.url.split('?')[0]; diff --git a/plugins/core/src/repl-service.ts b/plugins/core/src/plugin-socket-service.ts similarity index 80% rename from plugins/core/src/repl-service.ts rename to plugins/core/src/plugin-socket-service.ts index af30f8d2c..d2e84c3fe 100644 --- a/plugins/core/src/repl-service.ts +++ b/plugins/core/src/plugin-socket-service.ts @@ -4,29 +4,20 @@ import { once } from 'events'; import net from 'net'; export const ReplServiceNativeId = 'replservice'; +export const ConsoleServiceNativeId = 'consoleservice'; -export class ReplService extends ScryptedDeviceBase implements StreamService { - constructor(nativeId?: ScryptedNativeId) { - super(ReplServiceNativeId); +export class PluginSocketService extends ScryptedDeviceBase implements StreamService { + constructor(nativeId: ScryptedNativeId, public serviceName: string) { + super(nativeId); } - /* - * The input to this stream can send buffers for normal terminal data and strings - * for control messages. Control messages are JSON-formatted. - * - * The current implemented control messages: - * - * Start: { "interactive": boolean, "cmd": string[] } - * Resize: { "dim": { "cols": number, "rows": number } } - * EOF: { "eof": true } - */ async connectStream(input?: AsyncGenerator, options?: any): Promise> { const pluginId = options?.pluginId as string; if (!pluginId) throw new Error('must provide pluginId'); const plugins = await sdk.systemManager.getComponent('plugins'); - const replPort: number = await plugins.getRemoteServicePort(pluginId, 'repl'); + const replPort: number = await plugins.getRemoteServicePort(pluginId, this.serviceName); const socket = net.connect(replPort); await once(socket, 'connect'); @@ -61,6 +52,8 @@ export class ReplService extends ScryptedDeviceBase implements StreamService { yield await queue.dequeue(); } } + catch (e) { + } finally { socket.destroy(); } diff --git a/plugins/core/ui/src/components/ConsoleCard.vue b/plugins/core/ui/src/components/ConsoleCard.vue deleted file mode 100644 index b8acb5842..000000000 --- a/plugins/core/ui/src/components/ConsoleCard.vue +++ /dev/null @@ -1,114 +0,0 @@ - - \ No newline at end of file diff --git a/plugins/core/ui/src/components/Device.vue b/plugins/core/ui/src/components/Device.vue index ee2110069..2ec5548a3 100644 --- a/plugins/core/ui/src/components/Device.vue +++ b/plugins/core/ui/src/components/Device.vue @@ -22,11 +22,11 @@ - + - + @@ -198,7 +198,6 @@ import VueSlider from "vue-slider-component"; import "vue-slider-component/theme/material.css"; import LogCard from "./builtin/LogCard.vue"; -import ConsoleCard from "./ConsoleCard.vue"; import PtyComponent from "./builtin/PtyComponent.vue"; import { getComponentWebPath, @@ -380,7 +379,6 @@ export default { PluginAdvancedUpdate, VueSlider, LogCard, - ConsoleCard, PtyComponent, Readme, @@ -474,6 +472,12 @@ export default { onChange() { // console.log(JSON.stringify(this.device)); }, + async clearConsole() { + const plugins = await this.$scrypted.systemManager.getComponent( + "plugins" + ); + plugins.clearConsole(this.device.id); + }, cleanupListener() { if (this.listener) { this.listener.removeListener(); diff --git a/plugins/core/ui/src/components/builtin/PtyComponent.vue b/plugins/core/ui/src/components/builtin/PtyComponent.vue index 8547d1efb..230088af8 100644 --- a/plugins/core/ui/src/components/builtin/PtyComponent.vue +++ b/plugins/core/ui/src/components/builtin/PtyComponent.vue @@ -1,15 +1,45 @@