shardy
Version:
Framework for online games and applications on Node.js
203 lines • 8.31 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Server = void 0;
const ws_1 = require("ws");
const net_1 = require("net");
const Logger_1 = require("./Logger");
const Tools_1 = require("./Tools");
const Client_1 = require("./Client");
const Transport_1 = require("./Transport");
const Connection_1 = require("./Connection");
const Commander_1 = require("./Commander");
const http_1 = __importDefault(require("http"));
const Extension_1 = require("./Extension");
const ID_LENGTH = 10;
const CONNECTION_EVENT = 'connection';
const LISTENING_EVENT = 'listening';
const ERROR_EVENT = 'error';
const CLOSE_EVENT = 'close';
const UNCAUGHT_EXCEPTIONS = 'uncaughtException';
const UNHANDLED_REJECTION = 'unhandledRejection';
class Server {
constructor(host, port, service, options) {
this.host = host;
this.port = port;
this.service = service;
this.options = options;
this.log = new Logger_1.Logger([], Tools_1.Tools.getTag(module));
this.list = new Map();
this.extensionsBefore = new Array();
this.extensionsAfter = new Array();
this.catchExceptions();
this.http = http_1.default.createServer();
this.server = this.service.transport === Transport_1.TransportType.TCP ? new net_1.Server() : new ws_1.WebSocketServer({ server: this.http });
this.server.on(CONNECTION_EVENT, (socket, message) => this.onConnect(socket, message));
this.server.on(LISTENING_EVENT, () => this.onListening());
this.server.on(ERROR_EVENT, (error) => this.onError(error));
this.server.on(CLOSE_EVENT, () => this.onClose());
}
start() {
return __awaiter(this, void 0, void 0, function* () {
this.log.info(`${this.service.name} (${this.service.transport}) start`, Logger_1.LoggerScope.System);
switch (this.service.transport) {
case Transport_1.TransportType.TCP:
this.server.listen(this.port, this.host);
break;
case Transport_1.TransportType.WebSocket:
this.http.listen(this.port, this.host);
default:
break;
}
});
}
stop() {
return __awaiter(this, void 0, void 0, function* () {
this.log.info(`stop`, Logger_1.LoggerScope.System);
this.list.forEach((client) => {
client.kick(Commander_1.DisconnectReason.ServerDown);
});
this.list.clear();
switch (this.service.transport) {
case Transport_1.TransportType.TCP:
this.server.close();
break;
case Transport_1.TransportType.WebSocket:
this.http.close();
default:
break;
}
});
}
use(extension) {
return __awaiter(this, void 0, void 0, function* () {
if (extension.mode === Extension_1.ExtensionMode.Before) {
const index = this.extensionsBefore.indexOf(extension, 0);
if (index < 0) {
yield extension.init();
this.extensionsBefore.push(extension);
}
}
else {
const index = this.extensionsAfter.indexOf(extension, 0);
if (index < 0) {
yield extension.init();
this.extensionsAfter.push(extension);
}
}
this.log.info(`use extension ${extension.name}`, Logger_1.LoggerScope.System);
});
}
setFilter(filter) {
return __awaiter(this, void 0, void 0, function* () {
this.log.setFilter(filter);
this.list.forEach((client) => {
client.log.setFilter(filter);
});
this.extensionsBefore.forEach((extension) => {
extension.log.setFilter(filter);
});
this.extensionsAfter.forEach((extension) => {
extension.log.setFilter(filter);
});
});
}
clearFilter() {
return __awaiter(this, void 0, void 0, function* () {
this.log.clearFilter();
this.list.forEach((client) => {
client.log.clearFilter();
});
this.extensionsBefore.forEach((extension) => {
extension.log.clearFilter();
});
this.extensionsAfter.forEach((extension) => {
extension.log.clearFilter();
});
});
}
onConnect(socket, message) {
const ip = message ? message.socket.remoteAddress : socket.remoteAddress;
const id = Tools_1.Tools.generateId(ID_LENGTH);
const logger = new Logger_1.Logger([id, ip]);
logger.setFilter(this.log.getFilter());
const client = new Client_1.Client(new Connection_1.Connection(socket, this.service.transport), id, logger, this.service, this.options);
client.onDisconnect = (id, reason) => this.onDisconnect(id, reason);
client.onReady = () => this.onReady(client);
this.list.set(id, client);
this.extensionsBefore.forEach((item) => {
item.onClientConnect(client);
});
this.service.onConnect(client);
this.log.info(`connected ${id}|${ip}`, Logger_1.LoggerScope.Debug);
this.extensionsAfter.forEach((item) => {
item.onClientConnect(client);
});
}
onListening() {
this.extensionsBefore.forEach((item) => {
item.onServiceListening();
});
this.service.onListening(this.host, this.port);
this.log.info(`listening on ${this.host}:${this.port}`, Logger_1.LoggerScope.System);
this.extensionsAfter.forEach((item) => {
item.onServiceListening();
});
}
onError(error) {
this.service.onError(error);
this.log.error(`error: ${error}`, Logger_1.LoggerScope.System);
}
onClose() {
this.extensionsBefore.forEach((item) => {
item.onServiceClose();
});
this.service.onClose();
this.log.info(`closed`, Logger_1.LoggerScope.System);
this.extensionsAfter.forEach((item) => {
item.onServiceClose();
});
}
onReady(client) {
this.extensionsBefore.forEach((item) => {
item.onClientReady(client);
});
this.service.onReady(client);
this.extensionsAfter.forEach((item) => {
item.onClientReady(client);
});
}
onDisconnect(id, reason) {
const client = this.list.get(id);
this.extensionsBefore.forEach((item) => {
item.onClientDisconnect(client, reason);
});
this.service.onDisconnect(client, reason);
client.destroy();
this.list.delete(id);
this.log.info(`disconnected ${id}`, Logger_1.LoggerScope.Debug);
this.extensionsAfter.forEach((item) => {
item.onClientDisconnect(client, reason);
});
}
onException(error) {
new Logger_1.Logger([], Tools_1.Tools.getTag(module)).error(`unexpected exception: ${error.stack}`, Logger_1.LoggerScope.All);
}
catchExceptions() {
process.on(UNCAUGHT_EXCEPTIONS, this.onException);
process.on(UNHANDLED_REJECTION, this.onException);
}
}
exports.Server = Server;
//# sourceMappingURL=Server.js.map