capybara/frontend/connection.js
2022-08-26 22:09:08 +03:00

101 lines
2.8 KiB
JavaScript

import logger from "./logger.js";
import { getItem } from "./storage.js";
export const ConnectionEvent = {
Open: 0,
Closed: 1,
Ready: 2,
};
export default {
ws: null,
log: logger(["Connection"], ["log"]).log,
messageLog: logger(["Connection", "Message"], ["log"]).log,
url: getItem("server:gatewayBase"),
isReady: false,
reconnectTimeout: 0,
handlers: new Map(),
formatAuthString(password) {
return `%auth%${btoa(password)}`;
},
connect(password=getItem("auth:token")) {
this.ws = new WebSocket(this.url);
this.ws.onerror = (e) => this.log("Error", e);
this.ws.onopen = () => {
this.log("Open");
this.dispatch(ConnectionEvent.Open, 1);
this.reconnectTimeout = 0;
this.log("Sending authentication packet");
this.ws.send(`0${this.formatAuthString(password)}`); // send auth packet
};
this.ws.onmessage = ({ data }) => {
if (data === "1") {
this.isReady = true;
this.dispatch(ConnectionEvent.Ready, 1);
this.log("Handshake complete");
}
};
this.ws.onclose = ({ code }) => {
this.dispatch(ConnectionEvent.Closed, code);
if (code === 4001) {// code for bad auth
this.log("Closed due to bad auth - skipping reconnect");
return;
}
this.isReady = false;
this.reconnectTimeout += 400;
if (this.reconnectTimeout >= 30000)
this.reconnectTimeout = 30000;
this.log(`Closed - will reconnect in ${this.reconnectTimeout}ms`);
setTimeout(() => this.connect(password), this.reconnectTimeout);
}
},
sendMessage(code, params=[]) {
let message = code;
for (let i = 0; i < params.length; i++) {
const param = params[i];
if (i == params.length - 1)
message += param;
else
message += param + ";";
}
this.ws.send(message);
},
disconnect() {
this.ws.close();
},
dispatch(event, data) {
const eventHandlers = this.handlers.get(event);
if (!eventHandlers)
return;
eventHandlers.forEach(e => e(data));
},
subscribe(event, handler) {
if (!this.handlers.get(event)) {
this.handlers.set(event, new Set());
}
this.handlers.get(event).add(handler);
return handler; // can later be used for unsubscribe()
},
unsubscribe(event, handler) {
const eventHandlers = this.handlers.get(event);
if (!eventHandlers)
return;
eventHandlers.delete(handler);
if (eventHandlers.size < 1) {
this.handlers.delete(event);
}
},
};