mirror of
https://github.com/koush/scrypted.git
synced 2026-02-09 00:39:56 +00:00
189 lines
5.1 KiB
TypeScript
189 lines
5.1 KiB
TypeScript
import { RpcPeer, RpcSerializer } from "../rpc";
|
|
|
|
interface WebSocketEvent {
|
|
type: string;
|
|
reason?: string;
|
|
message?: string;
|
|
data?: string | ArrayBufferLike;
|
|
source?: any;
|
|
}
|
|
|
|
interface WebSocketEventListener {
|
|
(evt: WebSocketEvent): void;
|
|
}
|
|
|
|
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];
|
|
}
|
|
});
|
|
}
|
|
|
|
export interface WebSocketConnectCallbacks {
|
|
connect(e: Error, ws: WebSocketMethods): void;
|
|
end(): void;
|
|
error(e: Error): void;
|
|
data(data: string | ArrayBufferLike): void;
|
|
}
|
|
|
|
export interface WebSocketConnect {
|
|
(connection: WebSocketConnection, callbacks: WebSocketConnectCallbacks): void;
|
|
}
|
|
|
|
export interface WebSocketMethods {
|
|
send(message: string | ArrayBufferLike): void;
|
|
close(message: string): void;
|
|
}
|
|
|
|
export function createWebSocketClass(__websocketConnect: WebSocketConnect): any {
|
|
|
|
class WebSocket extends WebSocketEventTarget {
|
|
_url: string;
|
|
_protocols: string[];
|
|
readyState: number;
|
|
|
|
constructor(public connection: WebSocketConnection, protocols?: string[]) {
|
|
super();
|
|
this._url = connection.url;
|
|
this._protocols = protocols;
|
|
this.readyState = 0;
|
|
|
|
__websocketConnect(connection, {
|
|
connect: (e, ws) => {
|
|
// connect
|
|
if (e != null) {
|
|
this.dispatchEvent({
|
|
type: 'error',
|
|
message: e.toString(),
|
|
});
|
|
return;
|
|
}
|
|
|
|
this.readyState = 1;
|
|
this.dispatchEvent({
|
|
type: 'open',
|
|
});
|
|
},
|
|
end: () => {
|
|
// end
|
|
this.readyState = 3;
|
|
this.dispatchEvent({
|
|
type: 'close',
|
|
reason: 'closed',
|
|
});
|
|
},
|
|
error: (e: Error) => {
|
|
// error
|
|
this.readyState = 3;
|
|
this.dispatchEvent({
|
|
type: 'error',
|
|
message: e.toString(),
|
|
});
|
|
},
|
|
data: (data: string | ArrayBufferLike) => {
|
|
// data
|
|
this.dispatchEvent({
|
|
type: 'message',
|
|
data: data,
|
|
source: this,
|
|
});
|
|
}
|
|
})
|
|
}
|
|
|
|
send(message: string | ArrayBufferLike) {
|
|
this.connection.send(message);
|
|
}
|
|
|
|
get url() {
|
|
return this._url;
|
|
}
|
|
|
|
get extensions() {
|
|
return "";
|
|
}
|
|
|
|
close(reason: string) {
|
|
this.connection.close(reason);
|
|
}
|
|
}
|
|
|
|
defineEventAttribute(WebSocket.prototype, "close");
|
|
defineEventAttribute(WebSocket.prototype, "error");
|
|
defineEventAttribute(WebSocket.prototype, "message");
|
|
defineEventAttribute(WebSocket.prototype, "open");
|
|
|
|
return WebSocket;
|
|
}
|
|
|
|
export class WebSocketConnection implements WebSocketMethods {
|
|
[RpcPeer.PROPERTY_PROXY_PROPERTIES]: any;
|
|
|
|
[RpcPeer.PROPERTY_PROXY_ONEWAY_METHODS] = [
|
|
"send",
|
|
"close",
|
|
];
|
|
|
|
constructor(public url: string, public websocketMethods: WebSocketMethods) {
|
|
this[RpcPeer.PROPERTY_PROXY_PROPERTIES] = {
|
|
url,
|
|
}
|
|
}
|
|
|
|
send(message: string | ArrayBufferLike): void {
|
|
return this.websocketMethods.send(message);
|
|
}
|
|
close(message: string): void {
|
|
return this.websocketMethods.close(message);
|
|
}
|
|
}
|
|
|
|
export class WebSocketSerializer implements RpcSerializer {
|
|
WebSocket: ReturnType<typeof createWebSocketClass>;
|
|
|
|
serialize(value: any, serializationContext?: any) {
|
|
throw new Error("WebSocketSerializer should only be used for deserialization.");
|
|
}
|
|
|
|
deserialize(serialized: WebSocketConnection, serializationContext?: any) {
|
|
if (!this.WebSocket)
|
|
return undefined;
|
|
return new this.WebSocket(serialized);
|
|
}
|
|
}
|