MWSE/Source/WebSocket.js

123 lines
2.9 KiB
JavaScript

"use strict";
let websocket = require("websocket");
let {http} = require("./HTTPServer");
let {randomUUID} = require("crypto");
const { Client } = require("./Client.js");
console.log("Web Socket Protocol is ready");
http.addListener("upgrade",() => {
console.log("HTTP Upgrading to WebSocket");
})
let wsServer = new websocket.server({
httpServer: http,
autoAcceptConnections: true
});
let global = new Map();
let clients = new Map();
wsServer.addListener("connect",(socket) => {
let local = new Client();
let id = randomUUID();
socket.id = id;
local.id = id;
local.socket = socket;
local.created_at = new Date();
clients.set(id, local);
emit("connect", global, local);
socket.addListener("close",()=>{
emit("disconnect", global, local);
clients.delete(id);
});
socket.addListener("message",({type,utf8Data}) => {
if(type == "utf8")
{
let json;
try{
json = JSON.parse(utf8Data);
emit('services', global, local, json);
let [payload, id, action] = json;
if(typeof id === "string")
{
action = id;
}
emitService(global, local, id, payload, action);
}catch{
emit("messageError", global, local, utf8Data);
}
}
});
});
/**
* @type {Map<string, Function[]>}
*/
let events = new Map();
/**
* @type {Map<string, Function[]>}
*/
let services = []
/**
*
* @param {string} event
* @param {(global:Map<string, any>, client:Client, data:any) => any} func
*/
exports.addListener = (event, func) => {
if(!events.has(event))
{
events.set(event,[]);
};
events.get(event).push(func);
};
/**
*
* @param {string} event
* @param {(data:{global:Map<string, any>, client:Client, message:any,response:Function,end:Function,next:Function}) => any} func
*/
exports.addService = (func) => {
services.push(func);
};
function emit(event,...args)
{
if(events.has(event))
{
for (const callback of events.get(event)) {
callback(...args);
}
};
};
/**
*
* @param {Map} global
* @param {Client} local
* @param {number} id
* @param {{[key:string]:any}} payload
* @param {"R"|"S"} action
*/
async function emitService(global, client, id, payload, action)
{
let willContinue = false;
for (const callback of services) {
await callback({
message: payload,
action,
client,
global,
response:(obj)=>{
client.send([obj, id, 'C']) // continue
},
end:(obj)=>{
client.send([obj, id, 'E']) // stopped data stream (this channel)
},
next:function(){
willContinue = true;
}
});
if(willContinue === false) break;
}
};
exports.websocket = wsServer;