mirror of
https://github.com/koush/scrypted.git
synced 2026-03-20 16:40:24 +00:00
websocket cleanups
This commit is contained in:
@@ -3,6 +3,8 @@ const fs = require('fs');
|
||||
|
||||
const pkg = JSON.parse(fs.readFileSync('package.json'));
|
||||
pkg.scripts = {
|
||||
// alias
|
||||
"build": "scrypted-webpack",
|
||||
"prepublishOnly": "NODE_ENV=production scrypted-webpack",
|
||||
"prescrypted-vscode-launch": "scrypted-webpack",
|
||||
"scrypted-vscode-launch": "scrypted-deploy-debug",
|
||||
|
||||
@@ -79,7 +79,6 @@ module.exports = {
|
||||
Long: "long",
|
||||
|
||||
// browser provide plugin polyfills
|
||||
_websocket: path.resolve(__dirname, 'polyfill/websocket.js'),
|
||||
wrtc: path.resolve(__dirname, 'polyfill/nodejs/wrtc'),
|
||||
mdns: path.resolve(__dirname, 'polyfill/nodejs/mdns'),
|
||||
serialport: path.resolve(__dirname, 'polyfill/nodejs/serialport'),
|
||||
@@ -97,9 +96,6 @@ module.exports = {
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.SSDP_COV': false,
|
||||
}),
|
||||
new webpack.ProvidePlugin({
|
||||
WebSocket: '_websocket'
|
||||
}),
|
||||
],
|
||||
|
||||
optimization: {
|
||||
|
||||
@@ -379,8 +379,11 @@ async function createREPLServer(events: EventEmitter): Promise<number> {
|
||||
device
|
||||
});
|
||||
delete ctx.console;
|
||||
delete ctx.window;
|
||||
|
||||
const welcome = `JavaScript REPL variables:\n${Object.keys(ctx).map(key => ' ' + key).join('\n')}\n\n`;
|
||||
const replVariables = Object.keys(ctx).filter(key => key !== 'require');
|
||||
|
||||
const welcome = `JavaScript REPL variables:\n${replVariables.map(key => ' ' + key).join('\n')}\n\n`;
|
||||
socket.write(welcome);
|
||||
|
||||
const r = repl.start({
|
||||
|
||||
159
server/src/plugin/plugin-remote-websocket.ts
Normal file
159
server/src/plugin/plugin-remote-websocket.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
interface WebSocketEvent {
|
||||
type: string;
|
||||
reason?: string;
|
||||
message?: string;
|
||||
data?: string|ArrayBufferLike;
|
||||
source?: any;
|
||||
}
|
||||
|
||||
interface WebSocketEventListener {
|
||||
(evt: WebSocketEvent): void;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
class WebSocketEventTarget {
|
||||
events: { [type: string]: WebSocketEventListener[]} = {};
|
||||
|
||||
dispatchEvent(event: WebSocketEvent) {
|
||||
const list = this.events[event.type];
|
||||
if (!list) {
|
||||
return;
|
||||
}
|
||||
for (const l of list) {
|
||||
l(event);
|
||||
}
|
||||
}
|
||||
addEventListener(type: string, f: WebSocketEventListener) {
|
||||
let list = this.events[type];
|
||||
if (!list) {
|
||||
list = this.events[type] = [];
|
||||
}
|
||||
list.push(f);
|
||||
}
|
||||
removeEventListener(type: string, f: WebSocketEventListener) {
|
||||
const list = this.events[type];
|
||||
if (!list) {
|
||||
return;
|
||||
}
|
||||
const index = list.indexOf(f);
|
||||
if (index > -1) {
|
||||
list.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function defineEventAttribute(p: any, type: string) {
|
||||
Object.defineProperty(p, 'on' + type, {
|
||||
get: function () {
|
||||
throw new Error(`${type} is write only`);
|
||||
},
|
||||
set: function (f) {
|
||||
this.events[type] = [f];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
interface WebSocketEndCallback {
|
||||
(): void;
|
||||
}
|
||||
|
||||
interface WebSocketErrorCallback {
|
||||
(e: Error): void;
|
||||
}
|
||||
|
||||
interface WebSocketDataCallback {
|
||||
(data: string | ArrayBufferLike): void;
|
||||
}
|
||||
|
||||
interface WebSocketSend {
|
||||
(message: string|ArrayBufferLike): void;
|
||||
}
|
||||
|
||||
interface WebSocketConnectCallback {
|
||||
(e: Error, ws: any, send: WebSocketSend): void;
|
||||
}
|
||||
|
||||
interface WebSocketConnect {
|
||||
(url: string, protocols: string[],
|
||||
connect: WebSocketConnectCallback,
|
||||
end: WebSocketEndCallback,
|
||||
error: WebSocketErrorCallback,
|
||||
data: WebSocketDataCallback): void;
|
||||
}
|
||||
|
||||
export function createWebSocketClass(__websocketConnect: WebSocketConnect) {
|
||||
|
||||
// @ts-ignore
|
||||
class WebSocket extends WebSocketEventTarget {
|
||||
_url: string;
|
||||
_protocols: string[];
|
||||
readyState: number;
|
||||
send: (message: string|ArrayBufferLike) => void;
|
||||
_ws: any;
|
||||
|
||||
constructor(url: string, protocols?: string[]) {
|
||||
super();
|
||||
this._url = url;
|
||||
this._protocols = protocols;
|
||||
this.readyState = 0;
|
||||
|
||||
__websocketConnect(url, protocols, (e, ws, send) => {
|
||||
// connect
|
||||
if (e != null) {
|
||||
this.dispatchEvent({
|
||||
type: 'error',
|
||||
message: e.toString(),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this._ws = ws;
|
||||
this.send = send;
|
||||
this.readyState = 1;
|
||||
this.dispatchEvent({
|
||||
type: 'open',
|
||||
});
|
||||
}, () => {
|
||||
// end
|
||||
this.readyState = 3;
|
||||
this.dispatchEvent({
|
||||
type: 'close',
|
||||
reason: 'closed',
|
||||
});
|
||||
}, (e: Error) => {
|
||||
// error
|
||||
this.readyState = 3;
|
||||
this.dispatchEvent({
|
||||
type: 'error',
|
||||
message: e.toString(),
|
||||
});
|
||||
}, (data: string | ArrayBufferLike) => {
|
||||
// data
|
||||
this.dispatchEvent({
|
||||
type: 'message',
|
||||
data: data,
|
||||
source: this,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
get url() {
|
||||
return this._url;
|
||||
}
|
||||
|
||||
get extensions() {
|
||||
return "";
|
||||
}
|
||||
|
||||
close() {
|
||||
this._ws.close();
|
||||
}
|
||||
}
|
||||
|
||||
defineEventAttribute(WebSocket.prototype, "close");
|
||||
defineEventAttribute(WebSocket.prototype, "error");
|
||||
defineEventAttribute(WebSocket.prototype, "message");
|
||||
defineEventAttribute(WebSocket.prototype, "open");
|
||||
|
||||
return WebSocket;
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import { BufferSerializer } from './buffer-serializer';
|
||||
import { Console } from 'console';
|
||||
import { EventEmitter, PassThrough } from 'stream';
|
||||
import { Writable } from 'node:stream';
|
||||
import { createWebSocketClass } from './plugin-remote-websocket';
|
||||
|
||||
class DeviceLogger implements Logger {
|
||||
nativeId: string;
|
||||
@@ -405,42 +406,39 @@ export function attachPluginRemote(peer: RpcPeer, options?: PluginRemoteAttachOp
|
||||
volume.writeFileSync(name, entry.getData());
|
||||
}
|
||||
|
||||
function websocketConnect(url: string, protocols: any, connect: any, end: any, error: any, data: any) {
|
||||
if (url.startsWith('io://')) {
|
||||
const id = url.substring('io://'.length);
|
||||
|
||||
ioSockets[id] = {
|
||||
data,
|
||||
error,
|
||||
end
|
||||
};
|
||||
|
||||
connect(undefined, {
|
||||
close: () => api.ioClose(id),
|
||||
}, (message: string) => api.ioSend(id, message));
|
||||
}
|
||||
else if (url.startsWith('ws://')) {
|
||||
const id = url.substring('ws://'.length);
|
||||
|
||||
ioSockets[id] = {
|
||||
data,
|
||||
error,
|
||||
end
|
||||
};
|
||||
|
||||
connect(undefined, {
|
||||
close: () => api.ioClose(id),
|
||||
}, (message: string) => api.ioSend(id, message));
|
||||
}
|
||||
else {
|
||||
throw new Error('unsupported websocket');
|
||||
}
|
||||
}
|
||||
|
||||
const params: any = {
|
||||
// legacy
|
||||
android: {},
|
||||
|
||||
__websocketConnect(url: string, protocols: any, connect: any, end: any, error: any, data: any) {
|
||||
if (url.startsWith('io://')) {
|
||||
const id = url.substring('io://'.length);
|
||||
|
||||
ioSockets[id] = {
|
||||
data,
|
||||
error,
|
||||
end
|
||||
};
|
||||
|
||||
connect(undefined, {
|
||||
close: () => api.ioClose(id),
|
||||
}, (message: string) => api.ioSend(id, message));
|
||||
}
|
||||
else if (url.startsWith('ws://')) {
|
||||
const id = url.substring('ws://'.length);
|
||||
|
||||
ioSockets[id] = {
|
||||
data,
|
||||
error,
|
||||
end
|
||||
};
|
||||
|
||||
connect(undefined, {
|
||||
close: () => api.ioClose(id),
|
||||
}, (message: string) => api.ioSend(id, message));
|
||||
}
|
||||
else {
|
||||
throw new Error('unsupported websocket');
|
||||
}
|
||||
},
|
||||
|
||||
window,
|
||||
require: (name: string) => {
|
||||
if (name === 'fs' && !packageJson.scrypted.realfs) {
|
||||
@@ -459,6 +457,7 @@ export function attachPluginRemote(peer: RpcPeer, options?: PluginRemoteAttachOp
|
||||
log,
|
||||
localStorage,
|
||||
pluginHostAPI: api,
|
||||
WebSocket: createWebSocketClass(websocketConnect),
|
||||
};
|
||||
|
||||
if (getDeviceConsole) {
|
||||
|
||||
Reference in New Issue
Block a user