diff --git a/src/Center/Center.ts b/src/Center/Center.ts index 2a3d4c6..f2e060e 100644 --- a/src/Center/Center.ts +++ b/src/Center/Center.ts @@ -273,6 +273,10 @@ export class Center implements SmppSession { this.defaultSingleJob = job; } + getPort(): number { + return this.port; + } + private validateSessions(reject: (reason?: any) => void) { if (this.sessions.length === 0) { reject(`No clients connected`); diff --git a/src/Center/CenterSessionManager.ts b/src/Center/CenterSessionManager.ts new file mode 100644 index 0000000..dd5ca23 --- /dev/null +++ b/src/Center/CenterSessionManager.ts @@ -0,0 +1,85 @@ +import EventEmitter from "events"; +import fs from "fs"; +import {Job} from "../Job/Job"; +import Logger from "../Logger"; +import {SessionManager} from "../SessionManager"; +import {SmppSession} from "../SmppSession"; +import {Center} from "./Center"; + +const CENTER_SESSIONS_FILE: string = process.env.CENTER_SESSIONS_FILE || "center_sessions.json"; + +export class CenterSessionManager extends SessionManager { + sessionId: number = 0; + sessions: Center[] = []; + identifier: string = "center"; + readonly logger: Logger = new Logger("CenterSessionManager"); + readonly eventEmitter: EventEmitter = new EventEmitter(); + + constructor() { + super(); + // super.eventEmitter.on(super.SESSION_ADDED_EVENT, (session: SmppSession) => this.eventEmitter.emit(this.SESSION_ADDED_EVENT, session)); + } + + setup(): void { + try { + this.logger.log1(`Loading clients from ${CENTER_SESSIONS_FILE}`) + let sessions: Buffer = fs.readFileSync(CENTER_SESSIONS_FILE); + let loadedSessions: any[] = JSON.parse(String(sessions)); + this.logger.log1(`Loaded ${loadedSessions.length} clients from ${CENTER_SESSIONS_FILE}`); + loadedSessions.forEach(session => { + this.createSession(session.url, session.username, session.password).then((sessionObj: SmppSession) => { + sessionObj.setDefaultSingleJob(Job.deserialize(session.defaultSingleJob)); + sessionObj.setDefaultMultipleJob(Job.deserialize(session.defaultMultipleJob)); + }); + }); + } catch (e) { + this.logger.log1(`Error loading clients from ${CENTER_SESSIONS_FILE}: ${e}`); + return; + } + } + + cleanup(): void { + this.logger.log1(`Saving clients to ${CENTER_SESSIONS_FILE}...`); + fs.writeFileSync(CENTER_SESSIONS_FILE, JSON.stringify(this.serialize(), null, 4)); + } + + createSession(port: number, username: string, password: string): Promise { + return new Promise((resolve, reject) => { + this.logger.log1(`Creating session with port ${port}`); + this.getSessionByPort(port).then(s => { + resolve(s); + }, err => { + }); + this.verifyPort(port, reject); + this.verifyUsername(username, reject); + this.verifyPassword(password, reject); + + let client = new Center(this.sessionId++, port, username, password); + this.addSession(client).then(() => { + resolve(client); + }); + }); + } + + getSessionByPort(port: number): Promise { + return new Promise((resolve, reject) => { + this.logger.log1(`Looking for session with port ${port}...`); + let session: SmppSession | undefined = this.sessions.find((s: Center) => s.getPort() === port); + if (session) { + this.logger.log1(`Found session with port ${port}`); + resolve(session); + } else { + this.logger.log1(`Session with port ${port} not found`); + reject(`Session with port ${port} not found`); + } + }); + } + + private verifyPort(port: number, reject: (reason?: any) => void) { + if (!port) { + let error = `Request to make a new center failed because of missing port.`; + this.logger.log1(error); + reject(error); + } + } +} \ No newline at end of file diff --git a/src/Client/ClientSessionManager.ts b/src/Client/ClientSessionManager.ts index c007c34..04cc8bd 100644 --- a/src/Client/ClientSessionManager.ts +++ b/src/Client/ClientSessionManager.ts @@ -1,52 +1,24 @@ import EventEmitter from "events"; import fs from "fs"; -import {Client} from "./Client"; import {Job} from "../Job/Job"; import Logger from "../Logger"; -import SessionManager from "../SessionManager"; +import {SessionManager} from "../SessionManager"; import {SmppSession} from "../SmppSession"; +import {Client} from "./Client"; const CLIENT_SESSIONS_FILE: string = process.env.CLIENT_SESSIONS_FILE || "client_sessions.json"; -export default class ClientSessionManager implements SessionManager { - sessionId: number; - sessions: Client[]; +export default class ClientSessionManager extends SessionManager { + sessionId: number = 0; + sessions: Client[] = []; + // Identifier is used in websockets to identify the type of session this manager manages identifier: string = "client"; - private readonly logger: any; - readonly SESSION_ADDED_EVENT: string = "SESSION ADDED"; - private readonly eventEmitter: EventEmitter = new EventEmitter(); + readonly logger: Logger = new Logger("ClientSessionManager"); + readonly eventEmitter: EventEmitter = new EventEmitter(); constructor() { - this.sessionId = 0; - this.sessions = []; - this.logger = new Logger("ClientSessionManager"); - } - - on(event: string, listener: (...args: any[]) => void): void { - this.eventEmitter.on(event, listener); - } - - getSessions(): Promise { - return new Promise(resolve => { - resolve(this.sessions); - }); - } - - addSession(session: SmppSession): Promise { - return new Promise((resolve, reject) => { - this.logger.log1(`Adding session with id ${session.getId()}`); - this.sessions.push(session as Client); - this.eventEmitter.emit(this.SESSION_ADDED_EVENT, session.getId()); - resolve(); - }); - } - - removeSession(session: SmppSession): Promise { - return new Promise((resolve, reject) => { - this.logger.log1(`Removing session with id ${session.getId()}`); - this.sessions = this.sessions.filter(s => s.getId() !== session.getId()); - resolve(); - }); + super(); + // super.eventEmitter.on(super.SESSION_ADDED_EVENT, (session: SmppSession) => this.eventEmitter.emit(this.SESSION_ADDED_EVENT, session)); } createSession(url: string, username: string, password: string): Promise { @@ -54,7 +26,8 @@ export default class ClientSessionManager implements SessionManager { this.logger.log1(`Creating session with url ${url}`); this.getSessionByUrl(url).then(s => { resolve(s); - }, err => {}); + }, err => { + }); this.verifyUrl(url, reject); this.verifyUsername(username, reject); this.verifyPassword(password, reject); @@ -66,24 +39,10 @@ export default class ClientSessionManager implements SessionManager { }); } - getSession(id: number): Promise { - return new Promise((resolve, reject) => { - this.logger.log1(`Looking for session with id ${id}...`); - let session: SmppSession | undefined = this.sessions.find(s => s.getId() === id); - if (session) { - this.logger.log1(`Found session with id ${id}`); - resolve(session); - } else { - this.logger.log1(`Session with id ${id} not found`); - reject(`Session with id ${id} not found`); - } - }); - } - getSessionByUrl(url: string): Promise { return new Promise((resolve, reject) => { this.logger.log1(`Looking for session with url ${url}...`); - let session: SmppSession | undefined = this.sessions.find(s => s.getUrl() === url); + let session: SmppSession | undefined = this.sessions.find((s: Client) => s.getUrl() === url); if (session) { this.logger.log1(`Found session with url ${url}`); resolve(session); @@ -94,13 +53,6 @@ export default class ClientSessionManager implements SessionManager { }); } - serialize(): object { - this.logger.log1(`Serializing ${this.sessions.length} clients`) - return this.sessions.map((session: SmppSession) => { - return session.serialize(); - }); - } - setup(): void { try { this.logger.log1(`Loading clients from ${CLIENT_SESSIONS_FILE}`) @@ -131,20 +83,4 @@ export default class ClientSessionManager implements SessionManager { reject(error); } } - - private verifyUsername(username: string, reject: (reason?: any) => void) { - if (!username) { - let error = `Request to make a new client failed because of missing username.`; - this.logger.log1(error); - reject(error); - } - } - - private verifyPassword(password: string, reject: (reason?: any) => void) { - if (!password) { - let error = `Request to make a new client failed because of missing password.`; - this.logger.log1(error); - reject(error); - } - } } \ No newline at end of file diff --git a/src/SessionManager.ts b/src/SessionManager.ts index df838a4..3965382 100644 --- a/src/SessionManager.ts +++ b/src/SessionManager.ts @@ -1,26 +1,80 @@ +import EventEmitter from "events"; +import Logger from "./Logger"; import {SmppSession} from "./SmppSession"; -export default interface SessionManager { - sessions: SmppSession[]; - sessionId: number; - identifier: string; - readonly SESSION_ADDED_EVENT: string; +export abstract class SessionManager { + abstract sessions: SmppSession[]; + abstract sessionId: number; + abstract identifier: string; + readonly SESSION_ADDED_EVENT: string = "SESSION ADDED"; + readonly logger: Logger = new Logger("SessionManager"); + readonly eventEmitter: EventEmitter = new EventEmitter(); - addSession(session: SmppSession): Promise; + addSession(session: SmppSession): Promise { + return new Promise((resolve, reject) => { + this.logger.log1(`Adding session with id ${session.getId()}`); + this.sessions.push(session); + this.eventEmitter.emit(this.SESSION_ADDED_EVENT, session.getId()); + resolve(); + }); + } - removeSession(session: SmppSession): Promise; + on(event: string, listener: (...args: any[]) => void): void { + this.eventEmitter.on(event, listener); + } - createSession(...args: any[]): Promise; + getSessions(): Promise { + return Promise.resolve(this.sessions); + } - getSession(id: number): Promise; + removeSession(session: SmppSession): Promise { + return new Promise((resolve, reject) => { + this.logger.log1(`Removing session with id ${session.getId()}`); + this.sessions = this.sessions.filter(s => s.getId() !== session.getId()); + resolve(); + }); + } - getSessions(): Promise; + getSession(id: number): Promise { + return new Promise((resolve, reject) => { + this.logger.log1(`Looking for session with id ${id}...`); + let session: SmppSession | undefined = this.sessions.find(s => s.getId() === id); + if (session) { + this.logger.log1(`Found session with id ${id}`); + resolve(session); + } else { + this.logger.log1(`Session with id ${id} not found`); + reject(`Session with id ${id} not found`); + } + }); + } - serialize(): object; + serialize(): object { + this.logger.log1(`Serializing ${this.sessions.length} clients`) + return this.sessions.map((session: SmppSession) => { + return session.serialize(); + }); + } - cleanup(): void; + // TODO: Maybe find a way to include write and read to file here too (instead of child classes) - setup(): void; + verifyUsername(username: string, reject: (reason?: any) => void) { + if (!username) { + let error = `Request to make a new client failed because of missing username.`; + this.logger.log1(error); + reject(error); + } + } - on(event: string, listener: (...args: any[]) => void): void; + verifyPassword(password: string, reject: (reason?: any) => void) { + if (!password) { + let error = `Request to make a new client failed because of missing password.`; + this.logger.log1(error); + reject(error); + } + } + + abstract cleanup(): void; + + abstract setup(): void; } \ No newline at end of file diff --git a/src/WS/ClientSet.ts b/src/WS/ClientSet.ts index f7138d9..34cf925 100644 --- a/src/WS/ClientSet.ts +++ b/src/WS/ClientSet.ts @@ -1,5 +1,5 @@ import Logger from "../Logger"; -import SessionManager from "../SessionManager"; +import {SessionManager} from "../SessionManager"; import {SmppSession} from "../SmppSession"; export class ClientSet { diff --git a/src/WS/WSServer.ts b/src/WS/WSServer.ts index 2d0498e..82b220e 100644 --- a/src/WS/WSServer.ts +++ b/src/WS/WSServer.ts @@ -1,6 +1,7 @@ import Logger from "../Logger"; -import SessionManager from "../SessionManager"; +import {SessionManager} from "../SessionManager"; import {ClientSet} from "./ClientSet"; + const WebSocket = require("ws"); const WS_SERVER_PORT: number = Number(process.env.WS_SERVER_PORT) || 8191; diff --git a/src/main.ts b/src/main.ts index edf2c3d..6d8ea4d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,7 +3,6 @@ import {Client} from "./Client/Client"; import ClientSessionManager from "./Client/ClientSessionManager"; import {Job} from "./Job/Job"; import Logger from "./Logger"; -import {WSServer} from "./WS/WSServer"; const smpp = require("smpp"); const fs = require("fs"); @@ -19,7 +18,6 @@ const {PDU} = require("smpp"); const app = express(); const SERVER_PORT: number = Number(process.env.SERVER_PORT) || 8190; -const CENTER_SESSIONS_FILE: string = process.env.CENTER_SESSIONS_FILE || "center_sessions.json"; const MESSAGE_SEND_UPDATE_DELAY: number = Number(process.env.MESSAGE_SEND_UPDATE_DELAY) || 500; // TODO: Add support for encodings