diff --git a/src/HttpServer/CenterRequestHandler.ts b/src/HttpServer/CenterRequestHandler.ts new file mode 100644 index 0000000..2f0b8ac --- /dev/null +++ b/src/HttpServer/CenterRequestHandler.ts @@ -0,0 +1,64 @@ +import {Center} from "../Center/Center"; +import {CenterSessionManager} from "../Center/CenterSessionManager"; +import Logger from "../Logger"; +import {PduProcessor} from "../PDUProcessor/PduProcessor"; +import {SessionManager} from "../SessionManager"; +import {SmppSession} from "../SmppSession"; +import {RequestHandler} from "./RequestHandler"; + +export class CenterRequestHandler extends RequestHandler { + sessionManager: CenterSessionManager; + logger: Logger = new Logger(this.constructor.name); + + constructor(sessionManager: SessionManager) { + super(); + this.sessionManager = sessionManager as CenterSessionManager; + } + + doGetAvailableProcessors(req: any, res: any): void { + this.logger.log1("Getting available processors"); + let processors: PduProcessor[] = PduProcessor.getProcessorsForType(Center.name); + res.send(processors.map((processor: any) => processor.serialize())); + } + + doGetAppliedProcessors(req: any, res: any): void { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + let processors: PduProcessor[] = session.pduProcessors; + res.send(processors.map((processor: any) => processor.serialize())); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doAddProcessor(req: any, res: any): void { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + let processor = PduProcessor.getProcessor(req.body.name); + PduProcessor.attachProcessor(session, processor); + res.send(session.serialize()); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doRemoveProcessor(req: any, res: any): void { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + let processor = PduProcessor.getProcessor(req.body.name); + PduProcessor.detachProcessor(session, processor); + res.send(session.serialize()); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doPost(req: any, res: any): void { + this.logger.log1("Creating client session"); + this.sessionManager.createSession(req.body.port, req.body.username, req.body.password).then((session: SmppSession) => { + res.send(session.serialize()); + }, (err: any) => { + this.logger.log1(`Failed to create client session: ${err}`); + res.status(500).send(); + }); + } + + doConnect(req: any, res: any): void { + throw new Error("Method not implemented."); + } + + doBind(req: any, res: any): void { + throw new Error("Method not implemented."); + } +} \ No newline at end of file diff --git a/src/HttpServer/ClientRequestHandler.ts b/src/HttpServer/ClientRequestHandler.ts new file mode 100644 index 0000000..8311529 --- /dev/null +++ b/src/HttpServer/ClientRequestHandler.ts @@ -0,0 +1,68 @@ +import {Client} from "../Client/Client"; +import ClientSessionManager from "../Client/ClientSessionManager"; +import Logger from "../Logger"; +import {SessionManager} from "../SessionManager"; +import {SmppSession} from "../SmppSession"; +import {RequestHandler} from "./RequestHandler"; + +export default class ClientRequestHandler extends RequestHandler { + sessionManager: ClientSessionManager; + logger: Logger = new Logger(this.constructor.name); + + constructor(sessionManager: SessionManager) { + super(); + this.sessionManager = sessionManager as ClientSessionManager; + } + + doGetAvailableProcessors(req: any, res: any): void { + throw new Error("Method not implemented."); + } + + doGetAppliedProcessors(req: any, res: any): void { + throw new Error("Method not implemented."); + } + + doAddProcessor(req: any, res: any): void { + throw new Error("Method not implemented."); + } + + doRemoveProcessor(req: any, res: any): void { + throw new Error("Method not implemented."); + } + + doPost(req: any, res: any): void { + this.logger.log1("Creating client session"); + this.sessionManager.createSession(req.body.url, req.body.username, req.body.password).then((session: SmppSession) => { + res.send(session.serialize()); + }, (err: any) => { + this.logger.log1(`Failed to create client session: ${err}`); + res.status(500).send(); + }); + } + + doBind(req: any, res: any): void { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + this.logger.log1(`Binding client session with ID ${req.params.id}`) + let client = session as Client; + client.doBind() + .then(() => res.send(session.serialize())) + .catch(err => res.status(400).send({ + err: true, + msg: err + })); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doConnect(req: any, res: any): void { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + this.logger.log1(`Connecting client session with ID ${req.params.id}`) + let client = session as Client; + client.doConnect() + .then(() => res.send(session.serialize())) + .catch(err => res.status(400).send({ + err: true, + msg: err + })); + }, this.handleSessionNotFound.bind(this, req, res)); + } +} \ No newline at end of file diff --git a/src/HttpServer/HttpServer.ts b/src/HttpServer/HttpServer.ts new file mode 100644 index 0000000..851a6d6 --- /dev/null +++ b/src/HttpServer/HttpServer.ts @@ -0,0 +1,66 @@ +import Logger from "../Logger"; +import {SessionManager} from "../SessionManager"; +import {CenterRequestHandler} from "./CenterRequestHandler"; +import ClientRequestHandler from "./ClientRequestHandler"; +import {RequestHandler} from "./RequestHandler"; + +const express = require("express"); +const bodyParser = require("body-parser"); + +const SERVER_PORT: number = Number(process.env.SERVER_PORT) || 8190; + +export class HttpServer { + private clientRequestHandler: RequestHandler; + private centerRequestHandler: RequestHandler; + + private app: any; + private server: any; + private readonly logger: Logger = new Logger(this.constructor.name); + + constructor(clientManager: SessionManager, centerManager: SessionManager) { + this.clientRequestHandler = new ClientRequestHandler(clientManager); + this.centerRequestHandler = new CenterRequestHandler(centerManager); + + this.app = express(); + this.app.use(bodyParser.json()); + + this.app.get('/api/client', this.clientRequestHandler.doGet.bind(this.clientRequestHandler)); + this.app.post('/api/client', this.clientRequestHandler.doPost.bind(this.clientRequestHandler)); + this.app.get('/api/client/:id', this.clientRequestHandler.doGetById.bind(this.clientRequestHandler)); + this.app.patch('/api/client/:id', this.clientRequestHandler.doPatch.bind(this.clientRequestHandler)); + this.app.put('/api/client/:id/send', this.clientRequestHandler.doConfigureSingleJob.bind(this.clientRequestHandler)); + this.app.post('/api/client/:id/send/default', this.clientRequestHandler.doSendSingleJob.bind(this.clientRequestHandler)); + this.app.post('/api/client/:id/send', this.clientRequestHandler.doSend.bind(this.clientRequestHandler)); + this.app.put('/api/client/:id/sendMany', this.clientRequestHandler.doConfigureManyJob.bind(this.clientRequestHandler)); + this.app.post('/api/client/:id/sendMany/default', this.clientRequestHandler.doSendManyJob.bind(this.clientRequestHandler)); + this.app.post('/api/client/:id/sendMany', this.clientRequestHandler.doSendMany.bind(this.clientRequestHandler)); + this.app.delete('/api/client/:id/sendMany', this.clientRequestHandler.doCancelSendMany.bind(this.clientRequestHandler)); + this.app.post('/api/client/:id/bind', this.clientRequestHandler.doBind.bind(this.clientRequestHandler)); + this.app.post('/api/client/:id/connect', this.clientRequestHandler.doConnect.bind(this.clientRequestHandler)); + this.app.delete('/api/client/:id/connect', this.clientRequestHandler.doDisconnect.bind(this.clientRequestHandler)); + this.app.delete('/api/client/:id', this.clientRequestHandler.doDelete.bind(this.clientRequestHandler)); + + this.app.get('/api/center', this.centerRequestHandler.doGet.bind(this.centerRequestHandler)); + this.app.post('/api/center', this.centerRequestHandler.doPost.bind(this.centerRequestHandler)); + this.app.get('/api/center/:id', this.centerRequestHandler.doGetById.bind(this.centerRequestHandler)); + this.app.patch('/api/center/:id', this.centerRequestHandler.doPatch.bind(this.centerRequestHandler)); + this.app.put('/api/center/:id/send', this.centerRequestHandler.doConfigureSingleJob.bind(this.centerRequestHandler)); + this.app.post('/api/center/:id/send/default', this.centerRequestHandler.doSendSingleJob.bind(this.centerRequestHandler)); + this.app.post('/api/center/:id/send', this.centerRequestHandler.doSend.bind(this.centerRequestHandler)); + this.app.put('/api/center/:id/sendMany', this.centerRequestHandler.doConfigureManyJob.bind(this.centerRequestHandler)); + this.app.post('/api/center/:id/sendMany/default', this.centerRequestHandler.doSendManyJob.bind(this.centerRequestHandler)); + this.app.post('/api/center/:id/sendMany', this.centerRequestHandler.doSendMany.bind(this.centerRequestHandler)); + this.app.delete('/api/center/:id/sendMany', this.centerRequestHandler.doCancelSendMany.bind(this.centerRequestHandler)); + this.app.delete('/api/center/:id/connect', this.centerRequestHandler.doDisconnect.bind(this.centerRequestHandler)); + this.app.delete('/api/center/:id', this.centerRequestHandler.doDelete.bind(this.centerRequestHandler)); + this.app.get('/api/center/processors', this.centerRequestHandler.doGetAppliedProcessors.bind(this.centerRequestHandler)); + this.app.get('/api/center/processors/all', this.centerRequestHandler.doGetAvailableProcessors.bind(this.centerRequestHandler)); + this.app.post('/api/center/processors', this.centerRequestHandler.doAddProcessor.bind(this.centerRequestHandler)); + this.app.delete('/api/center/processors', this.centerRequestHandler.doRemoveProcessor.bind(this.centerRequestHandler)); + + this.server = this.app.listen(SERVER_PORT, function () { + // @ts-ignore + this.logger.log1(`HTTPServer listening at http://localhost:${SERVER_PORT}`) + }.bind(this)); + } +} \ No newline at end of file diff --git a/src/HttpServer/RequestHandler.ts b/src/HttpServer/RequestHandler.ts new file mode 100644 index 0000000..26ee126 --- /dev/null +++ b/src/HttpServer/RequestHandler.ts @@ -0,0 +1,177 @@ +import {Job} from "../Job/Job"; +import Logger from "../Logger"; +import {SessionManager} from "../SessionManager"; +import {SmppSession} from "../SmppSession"; + +export abstract class RequestHandler { + abstract sessionManager: SessionManager; + logger: Logger = new Logger(this.constructor.name); + + doGet(req: any, res: any): void { + this.logger.log1("Getting client sessions"); + res.send(this.sessionManager.serialize()); + } + + doGetById(req: any, res: any): void { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + this.logger.log1(`Client session found with ID ${req.params.id}`) + res.send(session.serialize()); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doPatch(req: any, res: any): void { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + this.logger.log1(`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()); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doConfigureSingleJob(req: any, res: any): void { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + let job: Job = session.getDefaultSingleJob(); + if (job.pdu.source_addr && job.pdu.source_addr !== req.body.source) { + job.pdu.source_addr = req.body.source; + } + if (job.pdu.destination_addr && job.pdu.destination_addr !== req.body.destination) { + job.pdu.destination_addr = req.body.destination; + } + if (job.pdu.short_message && job.pdu.short_message !== req.body.message) { + job.pdu.short_message = req.body.message; + } + this.logger.log1(`Updating default job on session with ID ${req.params.id}`) + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doSendSingleJob(req: any, res: any): void { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + this.logger.log1(`Sending pre-configured message on session with ID ${req.params.id}`) + session.sendSingleDefault() + .then(pdu => res.send(pdu), + err => res.status(400).send({ + err: true, + message: err + })); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doSend(req: any, res: any): void { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + this.logger.log1(`Sending message on session with ID ${req.params.id}`) + let tempJob: Job = JSON.parse(JSON.stringify(session.defaultSingleJob)); + tempJob.pdu.source_addr = req.body.source; + tempJob.pdu.destination_addr = req.body.destination; + tempJob.pdu.short_message = req.body.message; + session.sendSingle(tempJob) + .then(pdu => res.send(pdu), + err => res.status(400).send({ + err: true, + message: err + })); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doConfigureManyJob(req: any, res: any): void { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + let perSecond: number = 1 / (req.body.interval / 1000) + let job: Job = session.getDefaultMultipleJob(); + if (!job.pdu.source_addr && job.pdu.source_addr !== req.body.source) { + job.pdu.source_addr = req.body.source; + } + if (!job.pdu.destination_addr && job.pdu.destination_addr !== req.body.destination) { + job.pdu.destination_addr = req.body.destination; + } + if (!job.pdu.short_message && job.pdu.short_message !== req.body.message) { + job.pdu.short_message = req.body.message; + } + if (!job.perSecond && job.perSecond !== perSecond) { + job.perSecond = perSecond; + } + if (!job.count && job.count !== req.body.count) { + job.count = req.body.count; + } + this.logger.log1(`Updating default job on session with ID ${req.params.id}`) + res.send(session.serialize()); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doSendManyJob(req: any, res: any): void { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + this.logger.log1(`Sending pre-configured messages on session with ID ${req.params.id}`) + session.sendMultipleDefault() + .then(() => res.send({}), + err => res.status(400).send({ + err: true, + message: err + })); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doSendMany(req: any, res: any) { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + this.logger.log1(`Sending message on session with ID ${req.params.id}`) + let tempJob: Job = JSON.parse(JSON.stringify(session.defaultMultipleJob)); + tempJob.pdu.source_addr = req.body.source; + tempJob.pdu.destination_addr = req.body.destination; + tempJob.pdu.short_message = req.body.message; + tempJob.perSecond = 1 / (req.body.interval / 1000); + tempJob.count = req.body.count; + session.sendMultiple(tempJob) + .then(pdu => res.send(pdu), + err => res.status(400).send({ + err: true, + message: err + })); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doCancelSendMany(req: any, res: any) { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + this.logger.log1(`Cancelling send timer for session with ID ${req.params.id}`); + session.cancelSendInterval(); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doDisconnect(req: any, res: any) { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + this.logger.log1(`Disconnecting session with ID ${req.params.id}`) + session.close().then(() => res.send(session.serialize()), err => res.status(400).send({ + err: true, + message: err + })); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + doDelete(req: any, res: any) { + this.sessionManager.getSession(req.params.id).then((session: SmppSession) => { + this.sessionManager.removeSession(session); + }, this.handleSessionNotFound.bind(this, req, res)); + } + + abstract doPost(req: any, res: any): void; + + abstract doConnect(req: any, res: any): void; + + abstract doBind(req: any, res: any): void; + + abstract doGetAvailableProcessors(req: any, res: any): void; + + abstract doGetAppliedProcessors(req: any, res: any): void; + + abstract doAddProcessor(req: any, res: any): void; + + abstract doRemoveProcessor(req: any, res: any): void; + handleSessionNotFound(req: any, res: any): void { + let error = `No session found with ID ${req.params.id}`; + this.logger.log1(error); + res.status(404).send({ + err: true, + message: error + }); + } +} \ No newline at end of file diff --git a/src/PDUProcessor/PduProcessor.ts b/src/PDUProcessor/PduProcessor.ts index ade4609..365e42e 100644 --- a/src/PDUProcessor/PduProcessor.ts +++ b/src/PDUProcessor/PduProcessor.ts @@ -42,7 +42,7 @@ export abstract class PduProcessor { PduProcessor.processors.push(new processor()); } - static getProcessorsForType(type: string): any[] { + static getProcessorsForType(type: string): PduProcessor[] { return this.processors.filter((processor: any) => processor.servesSessionType === type); } diff --git a/src/main.ts b/src/main.ts index ec05e56..480ffd5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,27 +2,15 @@ import {Center} from "./Center/Center"; import {CenterSessionManager} from "./Center/CenterSessionManager"; import {Client} from "./Client/Client"; import ClientSessionManager from "./Client/ClientSessionManager"; +import {HttpServer} from "./HttpServer/HttpServer"; import {Job} from "./Job/Job"; import Logger from "./Logger"; import {DebugPduProcessor} from "./PDUProcessor/DebugPduProcessor"; import {EchoPduProcessor} from "./PDUProcessor/EchoPduProcessor"; import {PduProcessor} from "./PDUProcessor/PduProcessor"; +import {WSServer} from "./WS/WSServer"; -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; - // TODO: Add support for encodings // TODO: Implement some sort of metrics on frontend by counting the pdus @@ -34,64 +22,8 @@ PduProcessor.addProcessor(EchoPduProcessor); let clientManager: ClientSessionManager = new ClientSessionManager(); let centerManager: CenterSessionManager = new CenterSessionManager(); -// let wss: WSServer = new WSServer([clientManager]); - -async function main() { - let client: Client = await clientManager.createSession("smpp://localhost:7000", "test", "test") as Client; - let center: Center = await centerManager.createSession(7000, "test", "test") as Center; - - let debugJobSingle = new Job(new PDU("submit_sm", { - source_addr: "1234567890", - destination_addr: "1234567890", - short_message: "Hello World" - })); - let debugJobMulti = new Job(new PDU("submit_sm", { - source_addr: "1234567890", - destination_addr: "1234567890", - short_message: "Hello World" - }), 10, 50); - - client.setDefaultSingleJob(debugJobSingle); - client.setDefaultMultipleJob(debugJobMulti); - - // // client.sendMultipleDefault(); - // - // // client.on(ClientEvents.ANY_PDU, (pdu: any) => console.log(pdu)); - // client.on(ClientEvents.STATUS_CHANGED, (state: any) => console.log(state)); - // client.setDefaultSingleJob(new Job(pdu1)); - // client.setDefaultMultipleJob(new Job(pdu1, 100, 10)); - // client.sendSingleDefault(); - // client.close().then(() => { - // console.log("CLOSED"); - // client.doConnect().then(() => { - // client.doBind().then(() => { - // client.sendMultipleDefault(); - // }, reason => console.log(reason)); - // }, err => console.log(err)); - // }, err => console.log(err)); - // }); - - // setInterval(() => { - // client.connectAndBind().then(() => { - // console.log("POGGIES"); - // client.close(); - // }); - // }, 1000); - // setTimeout(() => { - // center.sendMultiple(new Job(new PDU("deliver_sm", { - // source_addr: "1234567890", - // destination_addr: "1234567890", - // short_message: "Hello World" - // }), 10, 100)); - // // center.close(); - // }, 5000); - - // client.connectAndBind().then(() => { - // client.sendMultipleDefault(); - // }); -} - -main(); +let wss: WSServer = new WSServer([clientManager, centerManager]); +let httpServer: HttpServer = new HttpServer(clientManager, centerManager); function cleanup(): void { logger.log1("Cleaning up...");