nope/lib/communication/layers/IoSocketServer.ts

107 lines
3.0 KiB
TypeScript

/**
* @author Martin Karkowski
* @email m.karkowski@zema.de
* @create date 2020-11-06 08:52:42
* @modify date 2021-03-01 17:43:12
* @desc [description]
*/
import { Server } from "http";
import * as io from "socket.io";
import { generateId } from "../../helpers/idMethods";
import { getNopeLogger } from "../../logger/getLogger";
import { LoggerLevel } from "../../logger/nopeLogger";
import { Bridge } from "../bridge";
import { EventLayer } from "./eventLayer";
/**
* Communication Layer using IO-Sockets.
*
* @export
* @class IoSocketServer
* @implements {ICommunicationInterface}
*/
export class IoSocketServer extends Bridge {
protected _socket: io.Server;
protected _sockets: Set<io.Socket>;
/**
* Creates an instance of IoSocketServer.
* @param {number} port The Port, on which the Server should be hosted
* @param {("mirror" | "default")} [mode="default"] The Mode of the Server (it could be either a mirror-server or default-server)
* @param {LoggerLevel} [level="info"] Logger Level of the Layer
* @param {Server} [server] A Server shich should be used. (Otherwise a Server is created)
* @memberof IoSocketServer
*/
constructor(
public port: number,
level: LoggerLevel = "info",
server?: Server
) {
super(generateId(), "socket-io-server", level);
// If a server has been provided, we will use this, otherwise,
// we will create one.
if (server) {
this._socket = (io as any)(server);
} else {
this._socket = (io as any)({
allowRequest: (req, callback) => {
const noOriginHeader = req.headers.origin === undefined;
callback(null, true);
}
});
}
const _this = this;
this.connected.setContent(false);
this._logger.info(
"waiting for connection. Listening on port: " + port.toString()
);
this._socket.listen(port);
this._socket.on("connection", (client) => {
_this._logger.info("New Connection established: " + client.id);
// 1. Define a Custom Logger for the Client:
const logger = getNopeLogger("io-client-" + client.id, "info");
// 2. Create the Layer. Based on the Mode it will be either an Mirror or Default Layer.
const layer = new EventLayer(client as any, logger);
// 3. Add the Layer
this.addLayer(layer, true);
// Subscribe to Loosing connection:
client.on("disconnect", () => {
_this._logger.info("Connection of : " + client.id + " lost.");
_this._sockets.delete(client);
// Manually Remove the Layer
_this.removeLayer(layer);
if (_this._sockets.size === 0) {
_this.connected.setContent(false);
_this._logger.warn("All Connections lost");
}
});
_this.connected.forcePublish();
});
this._sockets = new Set();
}
async dispose() {
// Dispose the Connection Flag.
this.connected.dispose();
// Dispose every connection.
for (const client of this._sockets) {
client.disconnect();
}
}
}