123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- const http = require("http");
- const bsock = require("bsock");
- const uuid = require("uuid/v4");
- /* Responses */
- class Response {
- constructor(message) {
- this.message = message;
- }
- }
- exports.Response = Response;
- class SuccessResponse extends Response {
- constructor(message) {
- super(message);
- this.result = "Success";
- }
- }
- exports.SuccessResponse = SuccessResponse;
- class ErrorResponse extends Response {
- constructor(message = "Unknown error") {
- super(message);
- this.result = "Error";
- }
- }
- exports.ErrorResponse = ErrorResponse;
- class SubscriptionResponse extends SuccessResponse {
- constructor(uid, message) {
- super(message);
- this.uid = uid;
- }
- }
- exports.SubscriptionResponse = SubscriptionResponse;
- exports.rpcToRpcinfo = (rpc, owner) => {
- switch (rpc.type) {
- case "call":
- return {
- owner: owner,
- argNames: extractArgs(rpc.func),
- type: rpc.type,
- visibility: rpc.visibility,
- name: rpc.name,
- func: rpc.func,
- };
- case "unhook":
- return {
- owner: owner,
- argNames: extractArgs(rpc.func),
- type: rpc.type,
- visibility: rpc.visibility,
- name: rpc.name,
- func: rpc.func,
- };
- case "hook":
- const generator = hookGenerator(rpc);
- return {
- owner: owner,
- argNames: extractArgs(generator(undefined)),
- type: rpc.type,
- visibility: rpc.visibility,
- name: rpc.name,
- unhook: rpc.unhook,
- generator: generator,
- };
- }
- };
- exports.rpcHooker = (socket, owner, RPCs, makeUnique = true) => {
- const suffix = makeUnique ? "-" + uuid().substr(0, 4) : "";
- return RPCs.map(rpc => exports.rpcToRpcinfo(rpc, owner))
- .map(info => {
- const ret = info;
- ret.uniqueName = info.name + suffix;
- switch (info.type) {
- case "hook":
- socket.hook(ret.uniqueName, info.generator(socket));
- break;
- default:
- socket.hook(ret.uniqueName, info.func);
- }
- socket.on('close', () => socket.unhook(info.name));
- return ret;
- });
- };
- const hookGenerator = (rpc) => {
- const argsArr = extractArgs(rpc.func);
- argsArr.pop();
- const args = argsArr.join(',');
- return eval(`(socket) => async (` + args + `) => {
- const res = await rpc.func(` + args + (args.length !== 0 ? ',' : '') + ` (x) => {
- socket.call(res.uid, x)
- })
- if(res.result == 'Success'){
- socket.on('close', async () => {
- const unhookRes = await rpc.unhook(res.uid)
- console.log("Specific close handler for", rpc.name, res.uid, unhookRes)
- })
-
- }
- return res
- }`);
- };
- const extractArgs = (f) => {
- let fn = String(f);
- let args = fn.substr(0, fn.indexOf(")"));
- args = args.substr(fn.indexOf("(") + 1);
- let ret = args.split(",");
- return ret;
- };
- class RPCSocketServer {
- constructor(port, rpcExporters = [], conf = {
- errorHandler: (socket) => (error) => { socket.destroy(); console.error(error); },
- closeHandler: (socket) => () => { console.log("Socket closing"); },
- connectionHandler: (socket) => { console.log("New websocket connection in port " + socket.port); }
- }) {
- this.port = port;
- this.rpcExporters = rpcExporters;
- this.conf = conf;
- this.io = bsock.createServer();
- this.wsServer = http.createServer();
- this.startWebsocket();
- }
- startWebsocket() {
- try {
- this.io.attach(this.wsServer);
- this.io.on('socket', (socket) => {
- socket.on('error', this.conf.errorHandler(socket));
- socket.on('close', this.conf.closeHandler(socket));
- this.initApis(socket);
- });
- this.wsServer.listen(this.port);
- }
- catch (e) {
- //@ts-ignore
- this.errorHandler(undefined)("Unable to connect to socket");
- }
- }
- initApis(socket) {
- const adminRPCs = [
- {
- name: 'info',
- type: 'call',
- visibility: 'private',
- func: async () => rpcInfos
- }
- ];
- const rpcInfos = [
- ...exports.rpcHooker(socket, "Admin", adminRPCs, false),
- ...this.rpcExporters.flatMap(exporter => exports.rpcHooker(socket, exporter.name, exporter.exportRPCs()))
- ];
- }
- }
- exports.RPCSocketServer = RPCSocketServer;
|