You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
2.1 KiB
JavaScript

class WebSocketConnection extends Connection {
static priority = 800;
static name = 'WS';
#ws;
#packet_buffer;
#reconnect;
onConnChange(s){}
constructor(hub) {
super(hub);
this.options.enabled = false;
this.options.ip = false;
this.options.port = false;
this.options.connect_timeout = 3000;
this.#packet_buffer = new PacketBufferScanFirst(data => {
this.hub._parsePacket(this, data);
});
}
isConnected() {
return this.#ws && this.#ws.readyState == 1;
}
async begin(){}
async discover(){}
async search(){}
async connect() {
if (this.#ws) return;
this._setState(ConnectionState.CONNECTING);
this.#reconnect = true;
this.#ws = await WebSocketConnection.#wsOpenAsync(`ws://${this.options.ip}:${this.options.port}/`, ['hub'], this.options.connect_timeout);
this._setState(ConnectionState.CONNECTED);
this.#packet_buffer.clear();
this.#ws.onclose = async () => {
this._setState(ConnectionState.DISCONNECTED);
this.#ws = undefined;
await sleep(500);
if (this.#reconnect)
await this.connect();
};
this.#ws.onmessage = (e) => {
this.#packet_buffer.push(e.data);
};
}
async disconnect() {
this._setState(ConnectionState.DISCONNECTED);
this.#reconnect = false;
if (this.isConnected())
this.#ws.close();
}
async send(text) {
if (this.isConnected())
this.#ws.send(text);
}
/**
*
* @param {string} url
* @param {string[]} protos
* @param {number} timeout
* @returns {Promise<WebSocket>}
*/
static #wsOpenAsync(url, protos, timeout) {
return new Promise((res, rej) => {
const tid = setTimeout(handler, timeout);
function handler(e) {
ws.removeEventListener('open', handler);
ws.removeEventListener('error', handler);
clearTimeout(tid);
if (ws.readyState === WebSocket.OPEN)
res(ws);
else rej(e ?? new TimeoutError());
}
const ws = new WebSocket(url, protos);
ws.addEventListener('open', handler);
ws.addEventListener('error', handler);
})
}
}