From a26dbcc2311561dd825660c41bb0b24076e589ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Majdand=C5=BEi=C4=87?= Date: Tue, 28 Mar 2023 01:45:53 +0200 Subject: [PATCH] Port some amount of code to typescript --- .run/main.js.run.xml | 2 +- WebsocketTest.ts | 30 + package.json | 1 + src/client.ts | 118 +++ src/clientStatus.ts | 8 + src/job.ts | 9 + src/logger.ts | 72 ++ src/main.ts | 1685 ++++++++++++++++++++++++++++++++++++++++++ src/smppSession.ts | 16 + tsconfig.json | 14 + 10 files changed, 1954 insertions(+), 1 deletion(-) create mode 100644 WebsocketTest.ts create mode 100644 src/client.ts create mode 100644 src/clientStatus.ts create mode 100644 src/job.ts create mode 100644 src/logger.ts create mode 100644 src/main.ts create mode 100644 src/smppSession.ts create mode 100644 tsconfig.json diff --git a/.run/main.js.run.xml b/.run/main.js.run.xml index 71c8e4f..de16bf6 100644 --- a/.run/main.js.run.xml +++ b/.run/main.js.run.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/WebsocketTest.ts b/WebsocketTest.ts new file mode 100644 index 0000000..7be3c06 --- /dev/null +++ b/WebsocketTest.ts @@ -0,0 +1,30 @@ +// @ts-ignore +const Websocket = require('ws'); + +const ws = new Websocket('ws://localhost:8191'); +ws.on('open', function open() { + ws.send('something'); +}); + +interface Animal { + doNoise(): void; +} + +class Dog implements Animal { + doNoise(): void { + console.log("woof"); + } +} + +class Cat implements Animal { + doNoise(): void { + console.log("meow"); + } +} + +const dog = new Dog(); +dog.doNoise(); +const cat = new Cat(); +cat.doNoise(); +let animals: Animal[] = [dog, cat]; +animals.forEach(animal => animal.doNoise()); \ No newline at end of file diff --git a/package.json b/package.json index c3e70b7..d93d840 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "author": "", "license": "ISC", "dependencies": { + "@types/node": "^18.15.10", "body-parser": "^1.20.2", "express": "^4.18.2", "nanotimer": "^0.3.15", diff --git a/src/client.ts b/src/client.ts new file mode 100644 index 0000000..c5aaaf6 --- /dev/null +++ b/src/client.ts @@ -0,0 +1,118 @@ +import {SmppSession} from "./smppSession"; +import {Job} from "./job"; +import Logger from "./logger"; +import ClientStatus from "./clientStatus"; +import EventEmitter from "events"; + +export class Client implements SmppSession { + set username(value: string) { + this._username = value; + } + + set password(value: string) { + this._password = value; + } + + set url(value: string) { + this._url = value; + } + + set status(value: ClientStatus) { + this._status = value; + this.eventEmitter.emit(Client.ClientEvents.STATUS_CHANGED, this._status); + this.eventEmitter.emit(Client.ClientEvents.STATE_CHANGED, this.serialize()); + } + + public static ClientEvents = { + STATUS_CHANGED: "STATUS_CHANGED", + STATE_CHANGED: "STATE_CHANGED", + } + + private readonly eventEmitter: EventEmitter; + private readonly logger: object; + private readonly id: number; + private _username: string; + private _password: string; + private _url: string; + private session?: object; + private _status: ClientStatus = ClientStatus.NOT_CONNECTED; + + defaultSingleJob?: Job; + defaultMultipleJob?: Job; + + private promises: any = { + connect: null, + close: null, + bind: null + } + + constructor(id: number, url: string, username: string, password: string) { + this.id = id; + this._url = url; + this._username = username; + this._password = password; + + this.eventEmitter = new EventEmitter(); + this.logger = new Logger(`Client-${id}`); + this.setStatus(ClientStatus.NOT_CONNECTED) + + this.initialize(); + } + + setStatus(status: ClientStatus): void { + this._status = status; + this.eventEmitter.emit("status", status); + } + + initialize(): void { + return; + } + + connect(): Promise { + this.promises.connect = new Promise((resolve, reject) => { + if (this._status !== ClientStatus.NOT_CONNECTED) { + this.logger.log1("Client already connected"); + reject("Client already connected"); + return; + } + this.logger.log1(`Client connecting to ${this._url}`); + this.setStatus(ClientStatus.CONNECTING); + try { + this.session = smpp.connect({ + url: this._url, + auto_enquire_link_period: this.auto_enquire_link_period, + }, this.connected.bind(this)); + this.session.on('error', this.error.bind(this)); + this.session.on('close', this.closed.bind(this)); + } catch (e) { + this.logger.log1("Client connection failed to " + this._url); + this.setStatus(ClientStatus.NOT_CONNECTED); + this.session.close(); + reject("Client connection failed to " + this._url); + } + this.connectingPromise.resolve = resolve; + this.connectingPromise.reject = reject; + }); + return this.connectingPromise.promise; + } + + serialize(): string { + throw new Error("Method not implemented."); + } + + close(): Promise { + throw new Error("Method not implemented."); + } + + sendMultiple(Job: object): Promise { + throw new Error("Method not implemented."); + } + + sendPdu(pdu: object): Promise { + throw new Error("Method not implemented."); + } + + sendSingle(Job: object): Promise { + throw new Error("Method not implemented."); + } +} \ No newline at end of file diff --git a/src/clientStatus.ts b/src/clientStatus.ts new file mode 100644 index 0000000..2270366 --- /dev/null +++ b/src/clientStatus.ts @@ -0,0 +1,8 @@ +export default class ClientStatus { + static readonly CONNECTING: string = "CONNECTING"; + static readonly CONNECTED: string = "CONNECTED"; + static readonly BUSY: string = "BUSY"; + static readonly BINDING: string = "BINDING"; + static readonly BOUND: string = "BOUND"; + static readonly NOT_CONNECTED: string = "NOT CONNECTED"; +} \ No newline at end of file diff --git a/src/job.ts b/src/job.ts new file mode 100644 index 0000000..3314bc3 --- /dev/null +++ b/src/job.ts @@ -0,0 +1,9 @@ +export class Job { + pdu: object; + perSecond?: number; + count?: number; + + serialize(): string { + return JSON.stringify(this); + } +} \ No newline at end of file diff --git a/src/logger.ts b/src/logger.ts new file mode 100644 index 0000000..59b6bdd --- /dev/null +++ b/src/logger.ts @@ -0,0 +1,72 @@ +// @ts-ignore +import {WriteStream} from "fs"; + +const fs = require('fs'); + +// @ts-ignore +const LOG_LEVEL: number = process.env.LOG_LEVEL || 6; +// @ts-ignore +const LOG_FILE: string = process.env.LOG_FILE || ""; + +export default class Logger { + private clazz: string; + private readonly logLevel: number; + private readonly logFile: string; + private readonly logFileWriteStream: WriteStream | null = null; + + constructor(clazz: string) { + this.clazz = clazz; + this.logLevel = LOG_LEVEL; + this.logFile = LOG_FILE; + + if (!!this.logFile) { + this.logFileWriteStream = fs.createWriteStream(this.logFile, {flags: 'a'}); + } + } + + leftPad(str: string, len: number, char: string): string { + str = String(str); + let i: number = -1; + len = len - str.length; + if (char === undefined) { + char = " "; + } + while (++i < len) { + str = char + str; + } + return str; + } + + log(logLevel: number, data: any): void { + if (typeof data === "object") { + data = JSON.stringify(data); + } + let date = new Date(); + + let year: string = this.leftPad(String(date.getFullYear()), 4, '0'); + let month: string = this.leftPad(String(date.getMonth() + 1), 2, '0'); + let day: string = this.leftPad(String(date.getDate()), 2, '0'); + + let hours: string = this.leftPad(String(date.getHours()), 2, '0'); + let minutes: string = this.leftPad(String(date.getMinutes()), 2, '0'); + let seconds: string = this.leftPad(String(date.getSeconds()), 2, '0'); + let milliseconds: string = this.leftPad(String(date.getMilliseconds()), 3, '0'); + + let datePrefix: string = `[${day}/${month}/${year}-${hours}:${minutes}:${seconds}:${milliseconds}]` + + let out: string = datePrefix.padEnd(30, ' ') + `[${this.clazz}]`.padEnd(28, ' ') + `(${logLevel})`.padEnd(8, ' ') + data; + if (logLevel <= this.logLevel) { + console.log(out); + } + if (!!this.logFileWriteStream) { + this.logFileWriteStream.write(out + "\n"); + } + } + + log1 = this.log.bind(this, 1); + log2 = this.log.bind(this, 2); + log3 = this.log.bind(this, 3); + log4 = this.log.bind(this, 4); + log5 = this.log.bind(this, 5); + log6 = this.log.bind(this, 6); +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..cea5ede --- /dev/null +++ b/src/main.ts @@ -0,0 +1,1685 @@ +import Logger from "./logger"; + +const smpp = require("smpp"); +const fs = require("fs"); +const path = require("path"); +const EventEmitter = require("events"); +const NanoTimer = require('nanotimer'); + +const express = require("express"); +const bodyParser = require("body-parser"); +const WebSocket = require("ws"); +const {PDU} = require("smpp"); + +const app = express(); + +const SERVER_PORT: number = Number(process.env.SERVER_PORT) || 8190; +const WS_SERVER_PORT: number = Number(process.env.WS_SERVER_PORT) || 8191; +const CLIENT_SESSIONS_FILE: string = process.env.CLIENT_SESSIONS_FILE || "client_sessions.json"; +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 +// TODO: Implement some sort of metrics on frontend by counting the pdus + +[ + 'debug', + 'log', + 'warn', + 'error' +].forEach((methodName: string) => { + // @ts-ignore + const originalLoggingMethod: object = console[methodName]; + // @ts-ignore + console[methodName] = (firstArgument, ...otherArguments) => { + // @ts-ignore + const originalPrepareStackTrace = Error.prepareStackTrace; + // @ts-ignore + Error.prepareStackTrace = (_, stack) => stack; + // @ts-ignore + const callee = new Error().stack[2]; + // @ts-ignore + Error.prepareStackTrace = originalPrepareStackTrace; + // @ts-ignore + const relativeFileName = path.relative(process.cwd(), callee.getFileName()); + // @ts-ignore + const prefix = `${relativeFileName}:${callee.getLineNumber()}:`; + // @ts-ignore + if (typeof firstArgument === 'string') { + // @ts-ignore + originalLoggingMethod(prefix + ' ' + firstArgument, ...otherArguments); + } else { + // @ts-ignore + originalLoggingMethod(prefix, firstArgument, ...otherArguments); + } + }; +}); + +let logger = new Logger("main"); + +import {Client} from "./client"; + +let client: Client = new Client(0, "smpp://localhost:7001", "test", "test"); + +// class ClientSession { +// // TODO: Enable requesting DRs +// private auto_enquire_link_period: number = 500; +// private eventEmitter: object = new EventEmitter(); +// configuredMessageJob = { +// source: "", +// destination: "", +// message: "", +// }; +// configuredMultiMessageJob = { +// source: "", +// destination: "", +// message: "", +// interval: 1000, +// count: 1, +// }; +// +// connectingPromise = { +// promise: null, +// resolve: null, +// reject: null +// } +// disconnectingPromise = { +// promise: null, +// resolve: null, +// reject: null +// } +// bindingPromise = { +// promise: null, +// resolve: null, +// reject: null +// } +// +// static STATUS_CHANGED_EVENT = "statusChanged"; +// static ANY_PDU_EVENT = "*"; +// static MESSAGE_SEND_COUNTER_UPDATE_EVENT = "messageSendCounterUpdate"; +// +// constructor(id, url, username, password) { +// this.id = id; +// this.logger = new Logger(`ClientSession-${this.id}`); +// this.url = url; +// +// this.username = username; +// this.password = password; +// +// this.logger.log1(`Client created with url ${this.url}, username ${this.username}, password ${this.password} and ID ${this.id}`); +// this.status = ClientSessionStatus.NOT_CONNECTED; +// } +// +// setUsername(username) { +// this.username = username; +// this.refresh(); +// } +// +// setPassword(password) { +// this.password = password; +// this.refresh(); +// } +// +// refresh() { +// this.logger.log1(`Refreshing client with url ${this.url} and id ${this.id}`); +// let status = this.status; +// this.close().catch(err => err); +// if (status === ClientSessionStatus.CONNECTED) { +// this.connect().catch(err => this.logger.log1(err)); +// } +// if (status === ClientSessionStatus.BOUND) { +// this.connect().then(() => { +// this.bind().catch((err => this.logger.log1(err))); +// }).catch((err => this.logger.log1(err))); +// } +// } +// +// setStatus(newStatus) { +// this.status = newStatus; +// this.eventEmitter.emit(ClientSession.STATUS_CHANGED_EVENT, newStatus); +// } +// +// connect() { +// this.connectingPromise.promise = new Promise((resolve, reject) => { +// if (this.status !== ClientSessionStatus.NOT_CONNECTED) { +// this.logger.log1("Client already connected"); +// reject("Client already connected"); +// return; +// } +// this.logger.log1(`Client connecting to ${this.url}`); +// this.setStatus(ClientSessionStatus.CONNECTING); +// try { +// this.session = smpp.connect({ +// url: this.url, +// auto_enquire_link_period: this.auto_enquire_link_period, +// }, this.connected.bind(this)); +// this.session.on('error', this.error.bind(this)); +// this.session.on('close', this.closed.bind(this)); +// } catch (e) { +// this.logger.log1("Client connection failed to " + this.url); +// this.setStatus(ClientSessionStatus.NOT_CONNECTED); +// this.session.close(); +// reject("Client connection failed to " + this.url); +// } +// this.connectingPromise.resolve = resolve; +// this.connectingPromise.reject = reject; +// }); +// return this.connectingPromise.promise; +// } +// +// closed() { +// this.logger.log1(`Client closed connection to ${this.url}`); +// this.setStatus(ClientSessionStatus.NOT_CONNECTED); +// } +// +// error(error) { +// if (error.code === "ETIMEOUT") { +// this.logger.log1("Client connection timed out to " + this.url); +// } else if (error.code === "ECONNREFUSED") { +// this.logger.log1("Client connection refused to " + this.url); +// } else { +// this.logger.log1("Client connection failed to " + this.url); +// } +// this.session.close(); +// this.connectingPromise.reject(error); +// this.setStatus(ClientSessionStatus.NOT_CONNECTED); +// } +// +// connected() { +// this.logger.log1("Client connected to " + this.url); +// this.setStatus(ClientSessionStatus.CONNECTED); +// this.session.on('debug', (type, msg, payload) => { +// if (type.includes('pdu.')) { +// this.eventEmitter.emit(msg, payload); +// this.eventEmitter.emit(ClientSession.ANY_PDU_EVENT, payload); +// } +// }); +// this.session.on('pdu', this.sessionPdu.bind(this)); +// this.connectingPromise.resolve(); +// } +// +// sessionPdu(pdu) { +// if (pdu.command === 'deliver_sm') { +// this.session.send(pdu.response()); +// } +// } +// +// bind() { +// this.bindingPromise.promise = new Promise((resolve, reject) => { +// if (this.status !== ClientSessionStatus.CONNECTED) { +// this.logger.log1(`Cannot bind, client not connected to ${this.url}`); +// reject(`Cannot bind, client not connected to ${this.url}`); +// return; +// } +// +// this.logger.log1("Trying to bind to " + this.url) +// if (this.status !== ClientSessionStatus.CONNECTED) { +// this.logger.log1(`Cannot bind, client not connected to ${this.url}`); +// return; +// } +// if (!!!this.username || !!!this.password) { +// this.logger.log1(`Cannot bind client, username or password not set`); +// return; +// } +// this.setStatus(ClientSessionStatus.BINDING); +// this.logger.log1(`Client binding to ${this.url} with username ${this.username} and password ${this.password}`); +// +// this.session.bind_transceiver({ +// system_id: this.username, +// password: this.password, +// registered_delivery: 1 +// }, this.bindReply.bind(this)); +// this.bindingPromise.resolve = resolve; +// this.bindingPromise.reject = reject; +// }); +// return this.bindingPromise.promise; +// } +// +// bindReply(pdu) { +// if (pdu.command_status === 0) { +// this.logger.log1(`Client bound to ${this.url} with username ${this.username} and password ${this.password}`); +// this.setStatus(ClientSessionStatus.BOUND); +// this.bindingPromise.resolve(); +// } else { +// this.logger.log1(`Client bind failed to ${this.url} with username ${this.username} and password ${this.password}`); +// this.setStatus(ClientSessionStatus.CONNECTED); +// this.bindingPromise.reject(); +// } +// } +// +// send(source, destination, message, force=false) { +// return new Promise((resolve, reject) => { +// if (!force && !this.canSend()) { +// this.logger.log1(`Client cannot send message, not bound to ${this.url} or busy`); +// reject(`Client cannot send message, not bound to ${this.url} or busy`); +// return; +// } +// this.logger.log1(`Client sending message from ${source} to ${destination} with message ${message}`); +// this.session.submit_sm({ +// source_addr: source, +// destination_addr: destination, +// short_message: message, +// registered_delivery: 1, +// message_id: 10 +// }, pdu => { +// resolve(pdu); +// }); +// }); +// } +// +// sendDefault() { +// return this.send(this.configuredMessageJob.source, this.configuredMessageJob.destination, this.configuredMessageJob.message); +// } +// +// configureDefault(source, destination, message) { +// this.configuredMessageJob = { +// source: source, +// destination: destination, +// message: message +// } +// } +// +// sendOnInterval(source, destination, message, interval, count) { +// return new Promise((resolve, reject) => { +// if (!this.canSend()) { +// this.logger.log1(`Client cannot send many message, not bound to ${this.url} or busy`); +// reject(`Client cannot send many message, not bound to ${this.url} or busy`); +// return; +// } +// this.setStatus(ClientSessionStatus.BUSY); +// let counter = 0; +// let previousUpdateCounter = 0; +// +// this.updateTimer = new NanoTimer(); +// this.updateTimer.setInterval(() => { +// if (previousUpdateCounter !== counter) { +// this.eventEmitter.emit(ClientSession.MESSAGE_SEND_COUNTER_UPDATE_EVENT, counter); +// previousUpdateCounter = counter; +// } +// }, '', `${MESSAGE_SEND_UPDATE_DELAY / 1000} s`); +// +// this.timer = new NanoTimer(); +// this.timer.setInterval(() => { +// if (count > 0 && counter >= count) { +// this.cancelSendInterval(); +// } else { +// this.send(source, destination, message, true) +// .catch(e => this.logger.log1(`Error sending message: ${e}`)); +// counter++; +// } +// }, '', `${interval} s`); +// resolve(); +// }); +// } +// +// sendDefaultInterval() { +// return this.sendOnInterval(this.configuredMultiMessageJob.source, this.configuredMultiMessageJob.destination, this.configuredMultiMessageJob.message, +// this.configuredMultiMessageJob.interval, this.configuredMultiMessageJob.count); +// } +// +// configureDefaultInterval(source, destination, message, interval, count) { +// this.configuredMultiMessageJob = { +// source: source, +// destination: destination, +// message: message, +// interval: interval, +// count: count +// } +// } +// +// cancelSendInterval() { +// if (!!this.timer) { +// this.timer.clearInterval(); +// this.updateTimer.clearInterval(); +// this.timer = null; +// this.updateTimer = null; +// } +// this.setStatus(ClientSessionStatus.BOUND); +// } +// +// close() { +// this.disconnectingPromise.promise = new Promise((resolve, reject) => { +// if (this.status !== ClientSessionStatus.BOUND && this.status !== ClientSessionStatus.CONNECTED) { +// this.logger.log1(`Cannot close client, not bound to ${this.url}`); +// reject(`Cannot close client, not bound to ${this.url}`); +// return; +// } +// this.logger.log1(`Client closing connection to ${this.url}`); +// this.session.close(); +// this.setStatus(ClientSessionStatus.NOT_CONNECTED); +// resolve(); +// }); +// return this.disconnectingPromise.promise; +// } +// +// on(event, callback) { +// this.eventEmitter.on(event, callback); +// } +// +// serialize() { +// return { +// id: this.id, +// url: this.url, +// username: this.username, +// password: this.password, +// status: this.status, +// configuredMessageJob: this.configuredMessageJob, +// configuredMultiMessageJob: this.configuredMultiMessageJob +// } +// } +// +// canSend() { +// return this.status === ClientSessionStatus.BOUND; +// } +// } + +// class ClientSessionManager { +// sessionIdCounter = 0; +// logger = new Logger("ClientSessionManager"); +// +// constructor() { +// this.sessions = {}; +// } +// +// createSession(url, username, password) { +// let urlB64 = btoa(url); +// if (this.sessions[urlB64]) { +// this.logger.log1(`Client to ${url} already exists`); +// return this.sessions[urlB64]; +// } +// this.logger.log1(`Creating client to ${url} with username ${username} and password ${password}`); +// let session = new ClientSession(this.sessionIdCounter++, url, username, password); +// this.addSession(session); +// return session; +// } +// +// addSession(session) { +// this.logger.log1(`Adding client with ID ${session.id}`); +// this.sessions[btoa(session.url)] = session; +// } +// +// deleteSession(session) { +// this.logger.log1(`Deleting client with ID ${session.id}`); +// if (session.status === ClientSessionStatus.BOUND || session.status === ClientSessionStatus.CONNECTED) { +// session.close(); +// } +// delete this.sessions[btoa(session.url)]; +// } +// +// getSession(id) { +// return Object.values(this.sessions).find((session) => { +// return session.id == id; +// }); +// } +// +// serialize() { +// return Object.values(this.sessions).map((session) => { +// return session.serialize(); +// }); +// } +// +// cleanup() { +// this.logger.log1(`Saving clients to ${CLIENT_SESSIONS_FILE}...`); +// fs.writeFileSync(CLIENT_SESSIONS_FILE, JSON.stringify(this.serialize(), null, 4)); +// } +// +// startup() { +// try { +// let sessions = fs.readFileSync(CLIENT_SESSIONS_FILE); +// sessions = JSON.parse(sessions); +// this.logger.log1(`Loaded ${sessions.length} clients from ${CLIENT_SESSIONS_FILE}...`); +// sessions.forEach(session => { +// let sessionObj = this.createSession(session.url, session.username, session.password); +// sessionObj.configuredMessageJob = session.configuredMessageJob; +// sessionObj.configuredMultiMessageJob = session.configuredMultiMessageJob; +// }); +// } catch (e) { +// this.logger.log1(`Error loading clients from ${CLIENT_SESSIONS_FILE}: ${e}`); +// } +// } +// } +// +// class CenterSessionStatus { +// static CONNECTED = "CONNECTED"; +// static WAITING_CONNECTION = "WAITING CONNECTION"; +// static CONNECTION_PENDING = "CONNECTION PENDING"; +// static BUSY = "BUSY"; +// } +// +// class CenterMode { +// static DEBUG = "DEBUG"; +// static ECHO = "ECHO"; +// static DR = "DR"; +// } +// +// class CenterSession { +// // TODO: If the port is in use this throws an exception, catch it and log it +// eventEmitter = new EventEmitter(); +// sessions = []; +// nextSession = 0; +// mode = CenterMode.DEBUG; +// configuredMessageJob = { +// source: "", +// destination: "", +// message: "", +// }; +// configuredMultiMessageJob = { +// source: "", +// destination: "", +// message: "", +// interval: 1000, +// count: 1, +// }; +// +// disconnectingPromise = { +// promise: null, +// resolve: null, +// reject: null +// } +// +// static STATUS_CHANGED_EVENT = "statusChanged"; +// static MODE_CHANGED_EVENT = "modeChanged"; +// static SESSION_CHANGED_EVENT = "sessionChanged"; +// static ANY_PDU_EVENT = "*"; +// static MESSAGE_SEND_COUNTER_UPDATE_EVENT = "messageSendCounterUpdate"; +// +// constructor(id, port, username, password) { +// this.id = id; +// this.logger = new Logger(`CenterSession-${this.id}`); +// this.port = port; +// +// this.username = username; +// this.password = password; +// +// this.server = smpp.createServer({}, this.connected.bind(this)); +// this.server.on('debug', (type, msg, payload) => { +// if (type.includes('pdu.')) { +// this.eventEmitter.emit(msg, payload); +// this.eventEmitter.emit(CenterSession.ANY_PDU_EVENT, payload); +// } +// }); +// this.server.listen(this.port); +// +// this.logger.log1(`Center created with port ${this.port}, username ${this.username}, password ${this.password} and ID ${this.id}`); +// this.status = CenterSessionStatus.WAITING_CONNECTION; +// } +// +// setStatus(newStatus) { +// this.status = newStatus; +// this.eventEmitter.emit(CenterSession.STATUS_CHANGED_EVENT, newStatus); +// } +// +// setUsername(username) { +// this.username = username; +// this.refresh(); +// } +// +// setPassword(password) { +// this.password = password; +// this.refresh(); +// } +// +// setMode(mode) { +// this.mode = Object.values(CenterMode)[mode]; +// this.eventEmitter.emit(CenterSession.MODE_CHANGED_EVENT, mode); +// } +// +// refresh() { +// this.close().catch(err => { +// }); +// } +// +// error(error) { +// if (error.code === "ETIMEOUT") { +// this.logger.log1("Center connection timed out to " + this.port); +// } else if (error.code === "ECONNREFUSED") { +// this.logger.log1("Center connection refused to " + this.port); +// } else { +// this.logger.log1("Center connection failed to " + this.port); +// } +// this.logger.log1(`Session on center croaked. Error: ${error}`); +// this.setStatus(CenterSessionStatus.CONNECTION_PENDING); +// } +// +// connected(session) { +// this.logger.log1("Center got a connection on port " + this.port); +// this.setStatus(CenterSessionStatus.CONNECTION_PENDING); +// +// session.on('error', this.error.bind(this)); +// session.on('close', this.sessionClosed.bind(this, session)); +// +// function bind_transciever(pdu) { +// this.logger.log1(`Center got a bind_transciever on port ${this.port} with system_id ${pdu.system_id} and password ${pdu.password}`); +// session.pause(); +// if (pdu.system_id === this.username && pdu.password === this.password) { +// this.logger.log1(`Center session connection successful`); +// session.send(pdu.response()); +// session.resume(); +// session.on('pdu', this.sessionPdu.bind(this, session)); +// this.addSession(session); +// if (this.sessions.length > 0) { +// this.setStatus(CenterSessionStatus.CONNECTED); +// } +// session.on('debug', (type, msg, payload) => { +// if (type.includes('pdu.')) { +// this.eventEmitter.emit(msg, payload); +// this.eventEmitter.emit(CenterSession.ANY_PDU_EVENT, payload); +// } +// }); +// } else { +// this.logger.log1(`Center session connection failed, invalid credentials`); +// session.send(pdu.response({ +// command_status: smpp.ESME_RBINDFAIL +// })); +// if (this.sessions.length === 0) { +// this.setStatus(CenterSessionStatus.WAITING_CONNECTION); +// } +// session.close(); +// this.session = null; +// } +// } +// +// session.on('bind_transceiver', bind_transciever.bind(this)); +// } +// +// sessionClosed(session) { +// this.logger.log1(`Center session closed on port ${this.port}`); +// delete this.sessions[this.sessions.indexOf(session)]; +// this.sessions = this.sessions.filter(Boolean); +// if (this.sessions.length === 0) { +// this.setStatus(CenterSessionStatus.WAITING_CONNECTION); +// } +// } +// +// sessionPdu(session, pdu) { +// if (pdu.command === 'submit_sm') { +// session.send(pdu.response()); +// if (this.mode === CenterMode.ECHO) { +// this.notify(pdu.destination_addr, pdu.source_addr, pdu.short_message); +// } +// // TODO: Figure out how DRs work +// if (this.mode === CenterMode.DR && pdu.registered_delivery === 1) { +// let drPdu = new PDU('deliver_sm', { +// receipted_message_id: pdu.message_id, +// esm_class: 4, +// message_state: 2, +// length: 0, +// }); +// this.send(drPdu).catch(err => console.log(err)); +// } +// } +// if (pdu.command === 'enquire_link') { +// session.send(pdu.response()); +// } +// } +// +// configureDefault(source, destination, message) { +// this.configuredMessageJob = { +// source: source, +// destination: destination, +// message: message +// } +// } +// +// notifyDefault() { +// return this.notify(this.configuredMessageJob.source, this.configuredMessageJob.destination, this.configuredMessageJob.message); +// } +// +// notify(source, destination, message, force=false) { +// return new Promise((resolve, reject) => { +// if (!force && !this.canSend()) { +// this.logger.log1(`Center cannot send message, no sessions active on ${this.port} or busy`); +// reject(`Center cannot send message, no sessions active on ${this.port} or busy`); +// return; +// } +// this.logger.log1(`Sending notify message from ${source} to ${destination} with message ${message}`); +// this.getNextSession().deliver_sm({ +// source_addr: source, +// destination_addr: destination, +// short_message: message, +// }, pdu => { +// resolve(pdu); +// }); +// }); +// } +// +// send(pdu) { +// return new Promise((resolve, reject) => { +// if (!this.canSend()) { +// this.logger.log1(`Center cannot send message, no sessions active on ${this.port} or busy`); +// reject(`Center cannot send message, no sessions active on ${this.port} or busy`); +// return; +// } +// this.getNextSession().send(pdu, pdu => { +// resolve(pdu); +// }); +// }); +// } +// +// configureDefaultInterval(source, destination, message, interval, count) { +// this.configuredMultiMessageJob = { +// source: source, +// destination: destination, +// message: message, +// interval: interval, +// count: count +// } +// } +// +// notifyDefaultInterval() { +// return this.notifyOnInterval(this.configuredMultiMessageJob.source, this.configuredMultiMessageJob.destination, this.configuredMultiMessageJob.message, +// this.configuredMultiMessageJob.interval, this.configuredMultiMessageJob.count); +// } +// +// notifyOnInterval(source, destination, message, interval, count) { +// return new Promise((resolve, reject) => { +// if (!this.canSend()) { +// this.logger.log1(`Center cannot send many message, no sessions active to ${this.port} or busy`); +// reject(`Center cannot send many message, no sessions active to ${this.port} or busy`); +// return; +// } +// this.setStatus(CenterSessionStatus.BUSY); +// this.timer = new NanoTimer(); +// let counter = 0; +// let previousUpdateCounter = 0; +// +// this.updateTimer = new NanoTimer(); +// this.updateTimer.setInterval(() => { +// if (previousUpdateCounter !== counter) { +// this.eventEmitter.emit(CenterSession.MESSAGE_SEND_COUNTER_UPDATE_EVENT, counter); +// previousUpdateCounter = counter; +// } +// }, '', `${MESSAGE_SEND_UPDATE_DELAY / 1000} s`); +// +// this.timer.setInterval(() => { +// if (count > 0 && counter >= count) { +// this.cancelNotifyInterval(); +// } else { +// this.notify(source, destination, message, true) +// .catch(e => this.logger.log1(`Error sending message: ${e}`)); +// counter++; +// } +// }, '', `${interval} s`); +// resolve(); +// }); +// } +// +// cancelNotifyInterval() { +// if (!!this.timer) { +// this.timer.clearInterval(); +// this.updateTimer.clearInterval(); +// this.timer = null; +// this.updateTimer = null; +// } +// this.setStatus(CenterSessionStatus.CONNECTED); +// } +// +// getNextSession() { +// if (this.sessions.length === 0) { +// return null; +// } +// let session = this.sessions[this.nextSession]; +// this.nextSession = (this.nextSession + 1) % this.sessions.length; +// return session; +// } +// +// getSessions() { +// return this.sessions.map(session => { +// return this.mapSession(session); +// }) +// } +// +// mapSession(session) { +// return { +// closed: session.closed, +// paused: session.paused, +// remoteAddress: session.remoteAddress, +// remotePort: session.remotePort, +// _id: session._id, +// deleted: session.deleted || false +// } +// } +// +// closeSession(sessionId) { +// this.logger.log1(`Closing center session ${sessionId}`); +// let session = this.sessions.find(session => session._id == sessionId); +// if (!!session) { +// session.close(); +// this.eventEmitter.emit(CenterSession.SESSION_CHANGED_EVENT, this.mapSession(session)); +// } +// } +// +// deleteSession(sessionId) { +// this.logger.log1(`Deleting center session ${sessionId}`); +// let session = this.sessions.find(session => session._id == sessionId); +// if (!!session) { +// session.close(); +// session.destroy(); +// session.deleted = true; +// this.eventEmitter.emit(CenterSession.SESSION_CHANGED_EVENT, this.mapSession(session)); +// delete this.sessions[this.sessions.indexOf(session)]; +// this.sessions = this.sessions.filter(Boolean); +// } +// } +// +// addSession(session) { +// this.logger.log1(`Adding center session ${session._id}`); +// let sessionInfo = this.mapSession(session); +// this.eventEmitter.emit(CenterSession.SESSION_CHANGED_EVENT, sessionInfo); +// this.sessions.push(session); +// } +// +// close() { +// this.disconnectingPromise.promise = new Promise((resolve, reject) => { +// if (this.status !== CenterSessionStatus.CONNECTED) { +// this.logger.log1(`Cannot close center, no sessions active ${this.port}`); +// reject(`Cannot close center, no sessions active ${this.port}`); +// return; +// } +// this.sessions.forEach(session => { +// session.close(); +// }); +// this.sessions = []; +// this.setStatus(CenterSessionStatus.WAITING_CONNECTION); +// resolve(); +// }); +// return this.disconnectingPromise.promise; +// } +// +// on(event, callback) { +// this.eventEmitter.on(event, callback); +// } +// +// serialize() { +// return { +// id: this.id, +// port: this.port, +// username: this.username, +// password: this.password, +// status: this.status, +// activeSessions: this.sessions.length, +// mode: this.mode, +// configuredMessageJob: this.configuredMessageJob, +// configuredMultiMessageJob: this.configuredMultiMessageJob, +// } +// } +// +// canSend() { +// return this.status === CenterSessionStatus.CONNECTED; +// } +// } +// +// class CenterSessionManager { +// sessionIdCounter = 0; +// logger = new Logger("CenterSessionManager"); +// +// constructor() { +// this.servers = {}; +// } +// +// createSession(port, username, password) { +// if (this.servers[port]) { +// this.logger.log1(`Center listening on ${port} already exists`); +// return this.servers[port]; +// } +// this.logger.log1(`Creating center listening on ${port} with username ${username} and password ${password}`); +// let session = new CenterSession(this.sessionIdCounter++, port, username, password); +// this.addSession(session); +// return session; +// } +// +// addSession(server) { +// this.logger.log1(`Adding center with ID ${server.id}`); +// this.servers[server.port] = server; +// } +// +// deleteSession(server) { +// this.logger.log1(`Deleting center with ID ${server.id}`); +// if (server.status === CenterSessionStatus.CONNECTED) { +// server.close(); +// } +// delete this.servers[server.port]; +// } +// +// getSession(id) { +// return Object.values(this.servers).find((session) => { +// return session.id == id; +// }); +// } +// +// serialize() { +// return Object.values(this.servers).map((servers) => { +// return servers.serialize(); +// }); +// } +// +// cleanup() { +// this.logger.log1(`Saving centers to ${CENTER_SESSIONS_FILE}...`); +// fs.writeFileSync(CENTER_SESSIONS_FILE, JSON.stringify(this.serialize(), null, 4)); +// } +// +// startup() { +// try { +// let servers = fs.readFileSync(CENTER_SESSIONS_FILE); +// servers = JSON.parse(servers); +// this.logger.log1(`Loaded ${servers.length} centers from ${CENTER_SESSIONS_FILE}...`); +// servers.forEach(server => { +// let createdServer = this.createSession(server.port, server.username, server.password); +// if (!!server.mode) { +// createdServer.mode = server.mode; +// } +// createdServer.configuredMessageJob = server.configuredMessageJob; +// createdServer.configuredMultiMessageJob = server.configuredMultiMessageJob; +// }); +// } catch (e) { +// this.logger.log1(`Error loading centers from ${CLIENT_SESSIONS_FILE}: ${e}`); +// } +// } +// +// getAvailableCenterModes() { +// let modes = Object.values(CenterMode); +// return modes.reduce((acc, curr, idx) => { +// acc[idx] = curr; +// return acc; +// }, {}); +// } +// } +// +// +// class HTTPServer { +// logger = new Logger("HTTPServer"); +// +// constructor() { +// app.use(bodyParser.json()); +// +// app.get('/api/client', this.getClientSessions.bind(this)); +// app.post('/api/client', this.createClientSession.bind(this)); +// app.get('/api/client/:id', this.getClientSessionById.bind(this)); +// app.patch('/api/client/:id', this.patchClientSession.bind(this)); +// app.put('/api/client/:id/send', this.configSend.bind(this)); +// app.post('/api/client/:id/send/default', this.sendConfig.bind(this)); +// app.post('/api/client/:id/send', this.send.bind(this)); +// app.put('/api/client/:id/sendMany', this.configSendMany.bind(this)); +// app.post('/api/client/:id/sendMany/default', this.sendManyConfig.bind(this)); +// app.post('/api/client/:id/sendMany', this.sendMany.bind(this)); +// app.delete('/api/client/:id/sendMany', this.cancelSendMany.bind(this)); +// app.post('/api/client/:id/bind', this.bindClientSession.bind(this)); +// app.post('/api/client/:id/connect', this.connectClientSession.bind(this)); +// app.delete('/api/client/:id/connect', this.disconnectClientSession.bind(this)); +// app.delete('/api/client/:id', this.deleteClientSession.bind(this)); +// +// app.get('/api/center', this.getCenterSessions.bind(this)); +// app.post('/api/center', this.createCenterSession.bind(this)); +// app.get('/api/center/modes', this.getAvailableModes.bind(this)); +// app.get('/api/center/:id', this.getCenterServerById.bind(this)); +// app.get('/api/center/:id/session', this.getCenterServerSessionsById.bind(this)); +// app.delete('/api/center/:id/session/:sessionId', this.closeCenterServerSessionById.bind(this)); +// app.delete('/api/center/:id/session/:sessionId/destroy', this.deleteCenterServerSessionById.bind(this)); +// app.patch('/api/center/:id', this.patchCenterServer.bind(this)); +// app.put('/api/center/:id/send', this.configNotify.bind(this)); +// app.post('/api/center/:id/send/default', this.notifyConfig.bind(this)); +// app.post('/api/center/:id/send', this.notify.bind(this)); +// app.put('/api/center/:id/sendMany', this.configNotifyMany.bind(this)); +// app.post('/api/center/:id/sendMany/default', this.notifyManyConfig.bind(this)); +// app.post('/api/center/:id/sendMany', this.notifyMany.bind(this)); +// app.delete('/api/center/:id/sendMany', this.cancelNotifyMany.bind(this)); +// app.delete('/api/center/:id/connect', this.disconnectCenterSession.bind(this)); +// app.delete('/api/center/:id', this.deleteCenterServer.bind(this)); +// +// this.server = app.listen(SERVER_PORT, function() { +// this.logger.log1(`HTTPServer listening at http://localhost:${SERVER_PORT}`) +// }.bind(this)); +// } +// +// // TODO: These requests deserve error handling +// +// getClientSessions(req, res) { +// this.logger.log1("Getting client sessions"); +// res.send(clientSessionManager.serialize()); +// } +// +// createClientSession(req, res) { +// this.logger.log1("Creating client session"); +// let session = clientSessionManager.createSession(req.body.url, req.body.username, req.body.password); +// res.send(session.serialize()); +// } +// +// getClientSessionById(req, res) { +// let session = clientSessionManager.getSession(req.params.id); +// this.logger.log1(`Getting client session by ID ${req.params.id}`); +// if (session) { +// this.logger.log1(`Client session found with ID ${req.params.id}`) +// res.send(session.serialize()); +// } else { +// this.logger.log1(`No client session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// patchClientSession(req, res) { +// let session = clientSessionManager.getSession(req.params.id); +// if (session) { +// this.logger.log1(`Client session found with ID ${req.params.id}`) +// if (!!req.body.username && req.body.username !== session.username) { +// session.setUsername(req.body.username); +// } +// if (!!req.body.password && req.body.password !== session.password) { +// session.setPassword(req.body.password); +// } +// res.send(session.serialize()); +// } else { +// this.logger.log1(`No client session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// configSend(req, res) { +// let session = clientSessionManager.getSession(req.params.id); +// let source = req.body.source; +// let destination = req.body.destination; +// let message = req.body.message; +// this.logger.log1(`Setting default message from ${source} to ${destination} with message ${message} on session with ID ${req.params.id}`) +// if (session) { +// session.configureDefault(source, destination, message); +// res.send(session.serialize()); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// sendConfig(req, res) { +// let session = clientSessionManager.getSession(req.params.id); +// this.logger.log1(`Sending pre-configured message on session with ID ${req.params.id}`) +// if (session) { +// session.sendDefault() +// .then(pdu => res.send(pdu)) +// .catch(err => res.status(400).send(JSON.stringify(err))); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// send(req, res) { +// let session = clientSessionManager.getSession(req.params.id); +// let source = req.body.source; +// let destination = req.body.destination; +// let message = req.body.message; +// this.logger.log1(`Sending message from ${source} to ${destination} with message ${message} on session with ID ${req.params.id}`) +// if (session) { +// session.send(source, destination, message) +// .then(pdu => res.send(pdu)) +// .catch(err => res.status(400).send(JSON.stringify(err))); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// configSendMany(req, res) { +// let session = clientSessionManager.getSession(req.params.id); +// let source = req.body.source; +// let destination = req.body.destination; +// let message = req.body.message; +// let interval = req.body.interval / 1000; +// let count = req.body.count; +// if (!!req.body.perSecond) { +// interval = 1 / req.body.perSecond; +// } +// let perSecond = 1 / interval; +// this.logger.log1( +// `Setting default ${count} messages from ${source} to ${destination} with message ${message} on session with ID ${req.params.id} at a rate of ${perSecond} per second.`); +// if (session) { +// session.configureDefaultInterval(source, destination, message, interval, count); +// res.send(session.serialize()); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// sendManyConfig(req, res) { +// let session = clientSessionManager.getSession(req.params.id); +// this.logger.log1(`Sending pre-configured messages on session with ID ${req.params.id}`) +// if (session) { +// session.sendDefaultInterval() +// .then(() => res.send({})) +// .catch(err => res.status(400).send(JSON.stringify(err))); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// sendMany(req, res) { +// let session = clientSessionManager.getSession(req.params.id); +// let source = req.body.source; +// let destination = req.body.destination; +// let message = req.body.message; +// let interval = req.body.interval / 1000; +// let count = req.body.count; +// if (!!req.body.perSecond) { +// interval = 1 / req.body.perSecond; +// } +// let perSecond = 1 / interval; +// this.logger.log1( +// `Sending ${count} messages from ${source} to ${destination} with message ${message} on session with ID ${req.params.id} at a rate of ${perSecond} per second.`); +// if (session) { +// session.sendOnInterval(source, destination, message, interval, count) +// .then(pdu => res.send(pdu)) +// .catch(err => res.status(400).send((err))); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// cancelSendMany(req, res) { +// let session = clientSessionManager.getSession(req.params.id); +// if (session.status !== ClientSessionStatus.BUSY) { +// res.status(400).send({ +// err: true, +// msg: `Session with ID ${req.params.id} is not sending messages` +// }); +// return; +// } +// this.logger.log1(`Cancelling send timer for session with ID ${req.params.id}`); +// if (session) { +// session.cancelSendInterval(); +// res.send({}); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// bindClientSession(req, res) { +// this.logger.log1(`Binding client session with ID ${req.params.id}`) +// // Maybe make this async? +// let session = clientSessionManager.getSession(req.params.id); +// if (session) { +// session.bind() +// .then(() => res.send(session.serialize())) +// .catch(err => res.status(400).send({ +// err: true, +// msg: err +// })); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// connectClientSession(req, res) { +// this.logger.log1(`Connecting client session with ID ${req.params.id}`) +// let session = clientSessionManager.getSession(req.params.id); +// if (session) { +// session.connect() +// .then(() => res.send(session.serialize())) +// .catch(err => res.status(400).send({ +// err: true, +// msg: err +// })); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// disconnectClientSession(req, res) { +// this.logger.log1(`Disconnecting client session with ID ${req.params.id}`) +// let session = clientSessionManager.getSession(req.params.id); +// if (session) { +// session.close() +// .then(() => res.send(session.serialize())) +// .catch(err => res.status(400).send({ +// err: true, +// msg: err +// })); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// deleteClientSession(req, res) { +// this.logger.log1(`Deleting client session with ID ${req.params.id}`); +// let session = clientSessionManager.getSession(req.params.id); +// if (session) { +// clientSessionManager.deleteSession(session); +// res.send({}); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// getCenterSessions(req, res) { +// this.logger.log1("Getting center sessions"); +// res.send(centerSessionManager.serialize()); +// } +// +// createCenterSession(req, res) { +// this.logger.log1("Creating center session"); +// let session = centerSessionManager.createSession(req.body.port, req.body.username, req.body.password); +// res.send(session.serialize()); +// } +// +// getCenterServerById(req, res) { +// let session = centerSessionManager.getSession(req.params.id); +// this.logger.log1(`Getting center session by ID ${req.params.id}`); +// if (session) { +// this.logger.log1(`Center session found with ID ${req.params.id}`) +// res.send(session.serialize()); +// } else { +// this.logger.log1(`No center session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// getCenterServerSessionsById(req, res) { +// let server = centerSessionManager.getSession(req.params.id); +// this.logger.log1(`Getting center session by ID ${req.params.id}`); +// if (server) { +// this.logger.log1(`Center session found with ID ${req.params.id}`) +// res.send(server.getSessions()); +// } else { +// this.logger.log1(`No center session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// closeCenterServerSessionById(req, res) { +// let server = centerSessionManager.getSession(req.params.id); +// this.logger.log1(`Getting center session by ID ${req.params.id}`); +// if (server) { +// this.logger.log1(`Center session found with ID ${req.params.id}`) +// server.closeSession(req.params.sessionId) +// res.send({}); +// } else { +// this.logger.log1(`No center session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// deleteCenterServerSessionById(req, res) { +// let server = centerSessionManager.getSession(req.params.id); +// this.logger.log1(`Getting center session by ID ${req.params.id}`); +// if (server) { +// this.logger.log1(`Center session found with ID ${req.params.id}`) +// server.deleteSession(req.params.sessionId) +// res.send({}); +// } else { +// this.logger.log1(`No center session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// patchCenterServer(req, res) { +// let server = centerSessionManager.getSession(req.params.id); +// if (server) { +// this.logger.log1(`Center server found with ID ${req.params.id}`) +// if (!!req.body.username && req.body.username !== server.username) { +// server.setUsername(req.body.username); +// } +// if (!!req.body.password && req.body.password !== server.password) { +// server.setPassword(req.body.password); +// } +// if (!!req.body.mode) { +// server.setMode(req.body.mode); +// } +// res.send(server.serialize()); +// } else { +// this.logger.log1(`No center server found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// getAvailableModes(req, res) { +// this.logger.log1("Getting available modes"); +// res.send(centerSessionManager.getAvailableCenterModes()); +// } +// +// configNotify(req, res) { +// let server = centerSessionManager.getSession(req.params.id); +// let source = req.body.source; +// let destination = req.body.destination; +// let message = req.body.message; +// this.logger.log1(`Setting default message from ${source} to ${destination} with message ${message} on server with ID ${req.params.id}`) +// if (server) { +// server.configureDefault(source, destination, message); +// res.send(server.serialize()); +// } else { +// this.logger.log1(`No server found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// notifyConfig(req, res) { +// let server = centerSessionManager.getSession(req.params.id); +// this.logger.log1(`Sending pre-configured message on server with ID ${req.params.id}`) +// if (server) { +// server.notifyDefault() +// .then(pdu => res.send(pdu)) +// .catch(err => res.status(400).send(JSON.stringify(err))); +// } else { +// this.logger.log1(`No server found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// notify(req, res) { +// let server = centerSessionManager.getSession(req.params.id); +// let source = req.body.source; +// let destination = req.body.destination; +// let message = req.body.message; +// this.logger.log1(`Sending notify message from ${source} to ${destination} with message ${message} on server with ID ${req.params.id}`) +// if (server) { +// server.notify(source, destination, message) +// .then(pdu => res.send(pdu)) +// .catch(err => res.status(400).send(err)); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// configNotifyMany(req, res) { +// let server = centerSessionManager.getSession(req.params.id); +// let source = req.body.source; +// let destination = req.body.destination; +// let message = req.body.message; +// let interval = req.body.interval / 1000; +// let count = req.body.count; +// if (!!req.body.perSecond) { +// interval = 1 / req.body.perSecond; +// } +// let perSecond = 1 / interval; +// this.logger.log1( +// `Setting default ${count} messages from ${source} to ${destination} with message ${message} on server with ID ${req.params.id} at a rate of ${perSecond} per second.`); +// if (server) { +// server.configureDefaultInterval(source, destination, message, interval, count); +// res.send(server.serialize()); +// } else { +// this.logger.log1(`No server found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// notifyManyConfig(req, res) { +// let server = centerSessionManager.getSession(req.params.id); +// this.logger.log1(`Sending pre-configured messages on server with ID ${req.params.id}`) +// if (server) { +// server.notifyDefaultInterval() +// .then(pdu => res.send(pdu)) +// .catch(err => res.status(400).send(JSON.stringify(err))); +// } else { +// this.logger.log1(`No server found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// notifyMany(req, res) { +// let server = centerSessionManager.getSession(req.params.id); +// let source = req.body.source; +// let destination = req.body.destination; +// let message = req.body.message; +// let interval = req.body.interval / 1000; +// let count = req.body.count; +// if (!!req.body.perSecond) { +// interval = 1 / req.body.perSecond; +// } +// let perSecond = 1 / interval; +// this.logger.log1( +// `Sending ${count} notify messages from ${source} to ${destination} with message ${message} on session with ID ${req.params.id} at a rate of ${perSecond} per second.`); +// if (server) { +// server.notifyOnInterval(source, destination, message, interval, count) +// .then(pdu => res.send(pdu)) +// .catch(err => res.status(400).send(err)); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// cancelNotifyMany(req, res) { +// let server = centerSessionManager.getSession(req.params.id); +// if (server.status !== ClientSessionStatus.BUSY) { +// res.status(400).send({ +// err: true, +// msg: `Session with ID ${req.params.id} is not sending messages` +// }); +// return; +// } +// this.logger.log1(`Cancelling send timer for server with ID ${req.params.id}`); +// if (server) { +// server.cancelNotifyInterval(); +// res.send({}); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// disconnectCenterSession(req, res) { +// this.logger.log1(`Disconnecting center session with ID ${req.params.id}`) +// let server = centerSessionManager.getSession(req.params.id); +// if (server) { +// server.close() +// .then(() => res.send(server.serialize())) +// .catch(err => res.status(400).send({ +// err: true, +// msg: err +// })); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// +// deleteCenterServer(req, res) { +// this.logger.log1(`Deleting center session with ID ${req.params.id}`); +// let server = centerSessionManager.getSession(req.params.id); +// if (server) { +// centerSessionManager.deleteSession(server); +// res.send({}); +// } else { +// this.logger.log1(`No session found with ID ${req.params.id}`); +// res.status(404).send(); +// } +// } +// } +// +// class WSServer { +// clients = {}; +// unknownClients = []; +// listenersAlreadySetup = []; +// +// constructor() { +// this.server = new WebSocket.Server({port: WS_SERVER_PORT}); +// this.logger = new Logger("WSServer"); +// this.server.on('connection', this.onConnection.bind(this)); +// this.logger.log1(`WSServer listening at ws://localhost:${WS_SERVER_PORT}`); +// } +// +// onConnection(ws) { +// this.logger.log1("New connection"); +// this.unknownClients.push(ws); +// ws.on('message', this.onMessage.bind(this, ws)); +// ws.on('close', this.onClose.bind(this, ws)); +// } +// +// addClient(ws, type, sessionId) { +// if (!this.clients[type]) { +// this.clients[type] = {}; +// } +// if (!this.clients[type][sessionId]) { +// this.clients[type][sessionId] = []; +// } +// this.logger.log1(`Adding client ${ws.id} to ${type} session ${sessionId}`); +// +// if (type === "client") { +// if (this.listenersAlreadySetup.indexOf(`client-${sessionId}`) === -1) { +// let session = clientSessionManager.getSession(sessionId); +// if (!!session) { +// this.logger.log1(`Setting up listeners for client session ${sessionId}`); +// session.on(ClientSession.STATUS_CHANGED_EVENT, this.onClientSessionStatusChange.bind(this, sessionId)); +// session.on(ClientSession.ANY_PDU_EVENT, this.onClientSessionPdu.bind(this, sessionId)); +// session.on(ClientSession.MESSAGE_SEND_COUNTER_UPDATE_EVENT, this.onClientMessageCounterUpdate.bind(this, sessionId)); +// } +// this.listenersAlreadySetup.push(`client-${sessionId}`); +// } else { +// this.logger.log1(`Listeners for client session ${sessionId} already set up`); +// } +// } else if (type === "center") { +// if (this.listenersAlreadySetup.indexOf(`center-${sessionId}`) === -1) { +// let session = centerSessionManager.getSession(sessionId); +// if (!!session) { +// this.logger.log1(`Setting up listeners for center session ${sessionId}`); +// session.on(CenterSession.STATUS_CHANGED_EVENT, this.onCenterStatusChange.bind(this, sessionId)); +// session.on(CenterSession.ANY_PDU_EVENT, this.onCenterServerPdu.bind(this, sessionId)); +// session.on(CenterSession.MODE_CHANGED_EVENT, this.onCenterModeChanged.bind(this, sessionId)); +// session.on(CenterSession.SESSION_CHANGED_EVENT, this.onCenterSessionsChanged.bind(this, sessionId)); +// session.on(ClientSession.MESSAGE_SEND_COUNTER_UPDATE_EVENT, this.onCenterMessageCounterUpdate.bind(this, sessionId)); +// } +// this.listenersAlreadySetup.push(`center-${sessionId}`); +// } else { +// this.logger.log1(`Listeners for center session ${sessionId} already set up`); +// } +// } +// +// this.clients[type][sessionId].push(ws); +// this.logger.log1(`Now active ${this.clients[type][sessionId].length} clients in session ID: ${sessionId} of type ${type}`); +// } +// +// onMessage(ws, message) { +// this.logger.log1("New message"); +// message = String(message); +// let data = message.split(":"); +// let type = data[0]; +// let sessionId = data[1]; +// +// this.logger.log1(`Moving client to session ID: ${sessionId} of type ${type}`); +// delete this.unknownClients[ws]; +// this.unknownClients = this.unknownClients.filter(Boolean); +// +// this.addClient(ws, type, sessionId); +// this.logger.log1(`Now active ${this.clients[type][sessionId].length} clients in session ID: ${sessionId} of type ${type}`); +// } +// +// onClose(ws) { +// this.removeClient(ws); +// // this.logger.log6(this.clients); +// this.logger.log1("Connection closed"); +// } +// +// removeClient(ws) { +// this.clients.client = this.removeFromArray(this.clients.client, ws); +// this.clients.center = this.removeFromArray(this.clients.center, ws); +// } +// +// removeFromArray(array, element) { +// for (let sessionId in array) { +// let index = array[sessionId].indexOf(element); +// if (index > -1) { +// delete array[sessionId][index]; +// } +// array[sessionId] = array[sessionId].filter(Boolean); +// if (array[sessionId].length === 0) { +// delete array[sessionId]; +// } +// } +// return array; +// } +// +// onClientSessionStatusChange(sessionId, newStatus) { +// this.logger.log1(`Session with ID ${sessionId} changed`); +// let payload = { +// objectType: "client", +// type: 'status', +// sessionId: sessionId, +// value: newStatus +// } +// let clients = this.clients["client"][sessionId]; +// if (!!clients) { +// this.logger.log1(`Broadcasting session with ID ${sessionId} to ${clients.length} clients`); +// clients.forEach(client => { +// client.send(JSON.stringify(payload)); +// }); +// } +// } +// +// onClientSessionPdu(sessionId, pdu) { +// // TODO: Maybe move this to an "ignored" array against who the pdu.command is compared +// if (pdu.command === 'enquire_link_resp' || pdu.command === 'enquire_link') { +// return; +// } +// let clients = this.clients["client"][sessionId]; +// if (!!clients) { +// this.logger.log2(`Session with ID ${sessionId} fired PDU`); +// let payload = { +// objectType: "client", +// type: 'pdu', +// sessionId: sessionId, +// value: pdu +// } +// this.logger.log2(`Broadcasting session with ID ${sessionId} to ${clients.length} clients`); +// clients.forEach(client => { +// client.send(JSON.stringify(payload)); +// }); +// } +// } +// +// onClientMessageCounterUpdate(sessionId, counter) { +// this.logger.log2(`Session with ID ${sessionId} updating message send counter`); +// let payload = { +// objectType: "client", +// type: 'counterUpdate', +// sessionId: sessionId, +// value: counter +// } +// let clients = this.clients["client"][sessionId]; +// if (!!clients) { +// this.logger.log2(`Broadcasting session with ID ${sessionId} to ${clients.length} clients`); +// clients.forEach(client => { +// client.send(JSON.stringify(payload)); +// }); +// } +// } +// +// onCenterStatusChange(sessionId, newStatus) { +// this.logger.log1(`Session with ID ${sessionId} changed`); +// let payload = { +// objectType: "center", +// type: 'status', +// sessionId: sessionId, +// value: newStatus +// } +// let clients = this.clients["center"][sessionId]; +// if (!!clients) { +// this.logger.log1(`Broadcasting session with ID ${sessionId} to ${clients.length} clients`); +// clients.forEach(client => { +// client.send(JSON.stringify(payload)); +// }); +// } +// } +// +// onCenterServerPdu(sessionId, pdu) { +// if (pdu.command === 'enquire_link_resp' || pdu.command === 'enquire_link') { +// return; +// } +// let clients = this.clients["center"][sessionId]; +// if (!!clients) { +// this.logger.log2(`Session with ID ${sessionId} fired PDU`); +// let payload = { +// objectType: "center", +// type: 'pdu', +// sessionId: sessionId, +// value: pdu +// } +// this.logger.log2(`Broadcasting session with ID ${sessionId} to ${clients.length} clients`); +// clients.forEach(client => { +// client.send(JSON.stringify(payload)); +// }); +// } +// } +// +// onCenterModeChanged(sessionId, newMode) { +// this.logger.log1(`Session with ID ${sessionId} changed`); +// let payload = { +// objectType: "center", +// type: 'mode', +// sessionId: sessionId, +// value: newMode, +// text: CenterMode[newMode] +// } +// let clients = this.clients["center"][sessionId]; +// if (!!clients) { +// this.logger.log1(`Broadcasting session with ID ${sessionId} to ${clients.length} clients`); +// clients.forEach(client => { +// client.send(JSON.stringify(payload)); +// }); +// } +// } +// +// onCenterSessionsChanged(sessionId, newSession) { +// this.logger.log1(`Session with ID ${sessionId} changed`); +// let payload = { +// objectType: "center", +// type: 'sessions', +// sessionId: sessionId, +// value: newSession +// } +// let clients = this.clients["center"][sessionId]; +// if (!!clients) { +// this.logger.log1(`Broadcasting session with ID ${sessionId} to ${clients.length} clients`); +// clients.forEach(client => { +// client.send(JSON.stringify(payload)); +// }); +// } +// } +// +// onCenterMessageCounterUpdate(sessionId, counter) { +// this.logger.log2(`Session with ID ${sessionId} updating message send counter`); +// let payload = { +// objectType: "center", +// type: 'counterUpdate', +// sessionId: sessionId, +// value: counter +// } +// let clients = this.clients["center"][sessionId]; +// if (!!clients) { +// this.logger.log2(`Broadcasting session with ID ${sessionId} to ${clients.length} clients`); +// clients.forEach(client => { +// client.send(JSON.stringify(payload)); +// }); +// } +// } +// } +// +// let clientSessionManager = new ClientSessionManager(); +// let centerSessionManager = new CenterSessionManager(); +// clientSessionManager.startup(); +// centerSessionManager.startup(); +// +// // let session = clientSessionManager.createSession('smpp://localhost:7001', 'test', 'test'); +// // let server = centerSessionManager.createSession(7001, 'test', 'test'); +// +// let session = clientSessionManager.getSession(0); +// let server = centerSessionManager.getSession(1); +// +// session.connect() +// .then(() => { +// session.bind().then(() => { +// // setTimeout(() => session.close(), 1000); +// }).catch(err => console.log(err)); +// }).catch(err => console.log(err)); +// +// // setTimeout(() => session.setUsername("test123"), 2000); +// // setTimeout(() => session.setPassword("test123"), 4000); +// +// // session.on(CenterSession.ANY_PDU_EVENT, (pdu) => { +// // console.log(pdu); +// // }); +// +// // session.on(ClientSession.ANY_PDU_EVENT, (pdu) => { +// // if (pdu.command.includes('enquire')) { +// // return; +// // } +// // console.log(pdu); +// // }); +// +// new WSServer(); +// new HTTPServer(); +// +// function cleanup() { +// clientSessionManager.cleanup(); +// centerSessionManager.cleanup(); +// process.exit(0); +// } +// +// process.on('exit', cleanup); +// process.on('SIGINT', cleanup); +// process.on('SIGUSR1', cleanup); +// process.on('SIGUSR2', cleanup); \ No newline at end of file diff --git a/src/smppSession.ts b/src/smppSession.ts new file mode 100644 index 0000000..646e564 --- /dev/null +++ b/src/smppSession.ts @@ -0,0 +1,16 @@ +export interface SmppSession { + username: string, + password: string, + + sendPdu(pdu: object): Promise; + + sendSingle(Job: object): Promise; + + sendMultiple(Job: object): Promise; + + close(): Promise; + + initialize(): void; + + serialize(): string; +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a93e486 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "moduleResolution": "node", + "esModuleInterop": true + }, + "exclude": [ + "./node_modules" + ] +}