Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4a5aa484ba | ||
a18ac0355c | |||
a1e7d3f885 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,3 +6,6 @@ client_sessions.json
|
||||
center_sessions.json
|
||||
dist
|
||||
main.exe
|
||||
.run
|
||||
.vscode
|
||||
build
|
||||
|
4
.prettierrc
Normal file
4
.prettierrc
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"tabWidth": 4,
|
||||
"useTabs": true
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Build To Web" type="ShConfigurationType">
|
||||
<option name="SCRIPT_TEXT" value="rsync -auzhvisP ./dist ../smsgw-tester-web/electron" />
|
||||
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||
<option name="SCRIPT_PATH" value="" />
|
||||
<option name="SCRIPT_OPTIONS" value="" />
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="false" />
|
||||
<envs />
|
||||
<method v="2">
|
||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="tsc" run_configuration_type="js.build_tools.npm" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
@@ -1,18 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="main.ts" type="TypeScriptProgramRunner" factoryName="TypeScript">
|
||||
<module name="smsgwtester" />
|
||||
<envs>
|
||||
<env name="LOG_LEVEL" value="0" />
|
||||
</envs>
|
||||
<option name="interpreterRef" value="project" />
|
||||
<option name="enabledTsNodeEsmLoader" value="false" />
|
||||
<option name="interpreterOptions" value="" />
|
||||
<option name="workingDirectory" value="C:\Users\Administrator\WebstormProjects\smsgwtester\src" />
|
||||
<option name="tsconfigFile" value="" />
|
||||
<option name="extraTypeScriptOptions" value="" />
|
||||
<option name="scriptName" value="$PROJECT_DIR$/src/main.ts" />
|
||||
<option name="programParameters" value="" />
|
||||
<option name="tsnodePackage" value="~\WebstormProjects\smsgwtester\node_modules\ts-node" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
@@ -1,14 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="pkg:windows" type="js.build_tools.npm" nameIsGenerated="true">
|
||||
<package-json value="$PROJECT_DIR$/package.json" />
|
||||
<command value="run" />
|
||||
<scripts>
|
||||
<script value="pkg:windows" />
|
||||
</scripts>
|
||||
<node-interpreter value="project" />
|
||||
<envs />
|
||||
<method v="2">
|
||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="tsc" run_configuration_type="js.build_tools.npm" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
@@ -1,12 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="tsc" type="js.build_tools.npm" nameIsGenerated="true">
|
||||
<package-json value="$PROJECT_DIR$/package.json" />
|
||||
<command value="run" />
|
||||
<scripts>
|
||||
<script value="tsc" />
|
||||
</scripts>
|
||||
<node-interpreter value="project" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
10
Dockerfile
Normal file
10
Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
||||
FROM ubuntu:22.04
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY "./main.exe/" "./"
|
||||
|
||||
EXPOSE 6555
|
||||
EXPOSE 6556
|
||||
|
||||
ENTRYPOINT "./main.exe"
|
29
README.md
29
README.md
@@ -70,10 +70,37 @@ With this preprocessor enabled the messages body is chopped up into segments bas
|
||||
|
||||
**With this preprocessor disabled any message whose body exceeds the maximum smpp message size is truncated to size**.
|
||||
|
||||
#### Protocol ID (+2/3 Digit Versions) (1.2)
|
||||
|
||||
This processor sets the protocol_id field to a value.
|
||||
The basic one (ProtocolIdProcessor) sets the value to 1, 2Digit version to 16 and 3Digit version to 128.
|
||||
|
||||
#### Source/Destination Set Processor
|
||||
|
||||
Generates X random numbers that are then used for sending Y messages.
|
||||
The interface with this processor is somewhat specific: To specify the amount of msisdns generated prepend "arg:X;" to the message body.
|
||||
Example: message "arg:100;test123" generates 100 msisdns and sends messages with the body of "test123".
|
||||
The point of this processor is to generate a set of msisdns to use with a greater number of messages.
|
||||
For example sending 100k messages from 100 msisdns (effectively sending 100 messages per msisdn) to simulate 100 users.
|
||||
Note, the picked msisdn per message is random (from the generated set).
|
||||
|
||||
### Center Preprocessors
|
||||
|
||||
None as of 1.0
|
||||
#### Destination & Source Enumerator (1.2)
|
||||
|
||||
Same as the Client version.
|
||||
|
||||
#### Long SMS (1.2)
|
||||
|
||||
Same as the Client version.
|
||||
|
||||
#### Protocol ID (+2/3 Digit Versions) (1.2)
|
||||
|
||||
Same as the Client version.
|
||||
|
||||
#### Source/Destination Set Processor (1.2)
|
||||
|
||||
Same as the Client version.
|
||||
|
||||
### Client Postprocessors
|
||||
|
||||
|
11
package.json
11
package.json
@@ -3,21 +3,26 @@
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"tsc": "tsc",
|
||||
"dev": "tsup && node build/main.cjs",
|
||||
"pkg:windows": "pkg ./dist/main.js --target node16-windows-x64 --output main.exe",
|
||||
"pkg:linux": "pkg ./dist/main.js --target node16-linux-x64 --output main.exe"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.4.9",
|
||||
"body-parser": "^1.20.2",
|
||||
"compression": "^1.7.4",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.18.2",
|
||||
"nanotimer": "^0.3.15",
|
||||
"smpp": "^0.6.0-rc.4",
|
||||
"smpp": "0.6.0-rc.4",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsup": "^7.2.0",
|
||||
"typescript": "^5.1.6",
|
||||
"ws": "^8.13.0",
|
||||
"zlib": "^1.0.5"
|
||||
}
|
||||
|
1705
pnpm-lock.yaml
generated
Normal file
1705
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
32
smpp_tester_options.json
Normal file
32
smpp_tester_options.json
Normal file
@@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"url": "smpp://localhost:4445",
|
||||
"connection_count": 8,
|
||||
"system_id": "snt",
|
||||
"password": "snt",
|
||||
"source_addr": "44455",
|
||||
"destination_addr": "test123",
|
||||
"short_message": "SNT BENCHMARK!",
|
||||
"message_count": 100
|
||||
},
|
||||
{
|
||||
"url": "smpp://172.17.77.204:4445",
|
||||
"connection_count": 8,
|
||||
"system_id": "snt",
|
||||
"password": "snt",
|
||||
"source_addr": "44455",
|
||||
"destination_addr": "test123",
|
||||
"short_message": "SNT BENCHMARK!",
|
||||
"message_count": 100
|
||||
},
|
||||
{
|
||||
"url": "smpp://172.17.77.14:4445",
|
||||
"connection_count": 8,
|
||||
"system_id": "snt",
|
||||
"password": "snt",
|
||||
"source_addr": "44455",
|
||||
"destination_addr": "test123",
|
||||
"short_message": "SNT BENCHMARK!",
|
||||
"message_count": 100
|
||||
}
|
||||
]
|
@@ -14,199 +14,199 @@ const smpp = require("smpp");
|
||||
const PORT_RELISTEN_DELAY: number = Number(process.env.PORT_RELISTEN_DELAY) || 500;
|
||||
|
||||
export default class Center extends SmppSession {
|
||||
readonly STATUSES: string[] = [
|
||||
"PORT BUSY",
|
||||
"WAITING CONNECTION",
|
||||
"CONNECTING",
|
||||
"CONNECTED",
|
||||
"BUSY"
|
||||
];
|
||||
_username: string;
|
||||
_password: string;
|
||||
_id: number;
|
||||
_status: string = this.STATUSES[0];
|
||||
port: number;
|
||||
readonly STATUSES: string[] = [
|
||||
"PORT BUSY",
|
||||
"WAITING CONNECTION",
|
||||
"CONNECTING",
|
||||
"CONNECTED",
|
||||
"BUSY"
|
||||
];
|
||||
_username: string;
|
||||
_password: string;
|
||||
_id: number;
|
||||
_status: string = this.STATUSES[0];
|
||||
port: number;
|
||||
|
||||
readonly logger: Logger;
|
||||
pendingSessions: any[] = [];
|
||||
sessions: any[] = [];
|
||||
private nextSession: number = 0;
|
||||
private server: any;
|
||||
readonly logger: Logger;
|
||||
pendingSessions: any[] = [];
|
||||
sessions: any[] = [];
|
||||
private nextSession: number = 0;
|
||||
private server: any;
|
||||
|
||||
constructor(id: number, port: number, username: string, password: string) {
|
||||
super();
|
||||
this._id = id;
|
||||
this._username = username;
|
||||
this._password = password;
|
||||
this.port = port;
|
||||
constructor(id: number, port: number, username: string, password: string) {
|
||||
super();
|
||||
this._id = id;
|
||||
this._username = username;
|
||||
this._password = password;
|
||||
this.port = port;
|
||||
|
||||
this._defaultSingleJob = Job.createEmptySingle('deliver_sm');
|
||||
this._defaultMultipleJob = Job.createEmptyMultiple('deliver_sm');
|
||||
this._defaultSingleJob = Job.createEmptySingle('deliver_sm');
|
||||
this._defaultMultipleJob = Job.createEmptyMultiple('deliver_sm');
|
||||
|
||||
ProcessorManager.attachProcessors(this, ProcessorManager.getProcessors(SubmitSmReplyProcessor.name));
|
||||
ProcessorManager.attachProcessors(this, ProcessorManager.getProcessors(BindTranscieverReplyProcessor.name));
|
||||
ProcessorManager.attachProcessors(this, ProcessorManager.getProcessors(EnquireLinkReplyProcessor.name));
|
||||
ProcessorManager.attachProcessors(this, ProcessorManager.getProcessors(SubmitSmReplyProcessor.name));
|
||||
ProcessorManager.attachProcessors(this, ProcessorManager.getProcessors(BindTranscieverReplyProcessor.name));
|
||||
ProcessorManager.attachProcessors(this, ProcessorManager.getProcessors(EnquireLinkReplyProcessor.name));
|
||||
|
||||
this.logger = new Logger(`Center-${id}`);
|
||||
this.logger = new Logger(`Center-${id}`);
|
||||
|
||||
this.initialize();
|
||||
}
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
_defaultSingleJob: Job;
|
||||
_defaultSingleJob: Job;
|
||||
|
||||
get defaultSingleJob(): Job {
|
||||
return this._defaultSingleJob;
|
||||
}
|
||||
get defaultSingleJob(): Job {
|
||||
return this._defaultSingleJob;
|
||||
}
|
||||
|
||||
set defaultSingleJob(job: Job) {
|
||||
if (job.pdu && !job.pdu.command) {
|
||||
job.pdu.command = 'deliver_sm';
|
||||
}
|
||||
super.defaultSingleJob = job;
|
||||
}
|
||||
set defaultSingleJob(job: Job) {
|
||||
if (job.pdu && !job.pdu.command) {
|
||||
job.pdu.command = 'deliver_sm';
|
||||
}
|
||||
super.defaultSingleJob = job;
|
||||
}
|
||||
|
||||
_defaultMultipleJob: Job;
|
||||
_defaultMultipleJob: Job;
|
||||
|
||||
get defaultMultipleJob(): Job {
|
||||
return this._defaultMultipleJob;
|
||||
}
|
||||
get defaultMultipleJob(): Job {
|
||||
return this._defaultMultipleJob;
|
||||
}
|
||||
|
||||
set defaultMultipleJob(job: Job) {
|
||||
if (job.pdu && !job.pdu.command) {
|
||||
job.pdu.command = 'deliver_sm';
|
||||
}
|
||||
super.defaultMultipleJob = job;
|
||||
}
|
||||
set defaultMultipleJob(job: Job) {
|
||||
if (job.pdu && !job.pdu.command) {
|
||||
job.pdu.command = 'deliver_sm';
|
||||
}
|
||||
super.defaultMultipleJob = job;
|
||||
}
|
||||
|
||||
sendPdu(pdu: PDU, force?: boolean): Promise<object> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!force) {
|
||||
this.validateSessions(reject);
|
||||
}
|
||||
this.logger.log5(`Center-${this.id} sending PDU: ${JSON.stringify(pdu)}`);
|
||||
let pduCopy = new smpp.PDU(pdu.command, {...pdu});
|
||||
let session = this.getNextSession();
|
||||
this.processors.Preprocessor.forEach((processor: PduProcessor) => processor.processPdu(session, pduCopy, this));
|
||||
this.doSendPdu(pduCopy, session).then((replyPdu: any) => {
|
||||
resolve(replyPdu);
|
||||
});
|
||||
});
|
||||
}
|
||||
sendPdu(pdu: PDU, force?: boolean): Promise<object> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!force) {
|
||||
this.validateSessions(reject);
|
||||
}
|
||||
let pduCopy = new smpp.PDU(pdu.command, {...pdu});
|
||||
let session = this.getNextSession();
|
||||
this.processors.Preprocessor.forEach((processor: PduProcessor) => processor.processPdu(session, pduCopy, this));
|
||||
this.logger.log5(`Center-${this.id} sending PDU: ${JSON.stringify(pduCopy)}`);
|
||||
this.doSendPdu(pduCopy, session).then((replyPdu: any) => {
|
||||
resolve(replyPdu);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
sendMultiple(job: Job): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.validateSessions(reject);
|
||||
if (!job.count || !job.perSecond) {
|
||||
reject(`Center-${this.id} sendMultiple failed: invalid job, missing fields`);
|
||||
}
|
||||
this.logger.log1(`Center-${this.id} sending multiple messages: ${JSON.stringify(job)}`);
|
||||
sendMultiple(job: Job): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.validateSessions(reject);
|
||||
if (!job.count || !job.perSecond) {
|
||||
reject(`Center-${this.id} sendMultiple failed: invalid job, missing fields`);
|
||||
}
|
||||
this.logger.log1(`Center-${this.id} sending multiple messages: ${JSON.stringify(job)}`);
|
||||
|
||||
let counter = 0;
|
||||
let previousUpdateCounter = 0;
|
||||
let counter = 0;
|
||||
let previousUpdateCounter = 0;
|
||||
|
||||
this.counterUpdateTimer.setInterval(() => {
|
||||
if (previousUpdateCounter !== counter) {
|
||||
this.eventEmitter.emit(this.EVENT.MESSAGE_SEND_COUNTER_UPDATE_EVENT, counter);
|
||||
previousUpdateCounter = counter;
|
||||
}
|
||||
}, '', `${this.MESSAGE_SEND_UPDATE_DELAY / 1000} s`);
|
||||
this.counterUpdateTimer.setInterval(() => {
|
||||
if (previousUpdateCounter !== counter) {
|
||||
this.eventEmitter.emit(this.EVENT.MESSAGE_SEND_COUNTER_UPDATE_EVENT, counter);
|
||||
previousUpdateCounter = counter;
|
||||
}
|
||||
}, '', `${this.MESSAGE_SEND_UPDATE_DELAY / 1000} s`);
|
||||
|
||||
let count = job.count || 1;
|
||||
let interval = 1 / (job.perSecond || 1);
|
||||
this.setStatus(4);
|
||||
this.sendTimer.setInterval(() => {
|
||||
if (count > 0 && counter >= count) {
|
||||
this.cancelSendInterval();
|
||||
} else {
|
||||
this.sendPdu(job.pdu, true);
|
||||
counter++;
|
||||
}
|
||||
}, '', `${interval} s`);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
let count = job.count || 1;
|
||||
let interval = 1 / (job.perSecond || 1);
|
||||
this.setStatus(4);
|
||||
this.sendTimer.setInterval(() => {
|
||||
if (count > 0 && counter >= count) {
|
||||
this.cancelSendInterval();
|
||||
} else {
|
||||
this.sendPdu(job.pdu, true);
|
||||
counter++;
|
||||
}
|
||||
}, '', `${interval} s`);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
initialize(): void {
|
||||
this.server = smpp.createServer({}, this.eventSessionConnected.bind(this));
|
||||
this.server.on('error', this.eventServerError.bind(this));
|
||||
this.doListen();
|
||||
this.setStatus(1);
|
||||
}
|
||||
initialize(): void {
|
||||
this.server = smpp.createServer({}, this.eventSessionConnected.bind(this));
|
||||
this.server.on('error', this.eventServerError.bind(this));
|
||||
this.doListen();
|
||||
this.setStatus(1);
|
||||
}
|
||||
|
||||
close(): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.logger.log1(`Center-${this.id} closing active connections`);
|
||||
this.sessions.forEach((session: any) => {
|
||||
session.close();
|
||||
});
|
||||
this.setStatus(1);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
close(): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.logger.log1(`Center-${this.id} closing active connections`);
|
||||
this.sessions.forEach((session: any) => {
|
||||
session.close();
|
||||
});
|
||||
this.setStatus(1);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
this.server.close();
|
||||
}
|
||||
destroy(): void {
|
||||
this.server.close();
|
||||
}
|
||||
|
||||
postSerialize(obj: any): object {
|
||||
obj.port = this.port;
|
||||
return obj;
|
||||
}
|
||||
postSerialize(obj: any): object {
|
||||
obj.port = this.port;
|
||||
return obj;
|
||||
}
|
||||
|
||||
updateStatus(): void {
|
||||
if (this.sessions.length > 0) {
|
||||
this.setStatus(3);
|
||||
} else if (this.pendingSessions.length > 0) {
|
||||
this.setStatus(2);
|
||||
} else {
|
||||
this.setStatus(1);
|
||||
}
|
||||
}
|
||||
updateStatus(): void {
|
||||
if (this.sessions.length > 0) {
|
||||
this.setStatus(3);
|
||||
} else if (this.pendingSessions.length > 0) {
|
||||
this.setStatus(2);
|
||||
} else {
|
||||
this.setStatus(1);
|
||||
}
|
||||
}
|
||||
|
||||
private doListen(): void {
|
||||
this.server.listen(this.port);
|
||||
}
|
||||
private doListen(): void {
|
||||
this.server.listen(this.port);
|
||||
}
|
||||
|
||||
private validateSessions(reject: (reason?: any) => void) {
|
||||
if (this.sessions.length === 0) {
|
||||
reject(`No clients connected`);
|
||||
}
|
||||
}
|
||||
private validateSessions(reject: (reason?: any) => void) {
|
||||
if (this.sessions.length === 0) {
|
||||
reject(`No clients connected`);
|
||||
}
|
||||
}
|
||||
|
||||
private getNextSession(): any {
|
||||
if (this.sessions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
let session = this.sessions[this.nextSession];
|
||||
this.nextSession = (this.nextSession + 1) % this.sessions.length;
|
||||
return session;
|
||||
}
|
||||
private getNextSession(): any {
|
||||
if (this.sessions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
let session = this.sessions[this.nextSession];
|
||||
this.nextSession = (this.nextSession + 1) % this.sessions.length;
|
||||
return session;
|
||||
}
|
||||
|
||||
private eventSessionConnected(session: any): void {
|
||||
this.logger.log1(`A client connected to center-${this.id}`);
|
||||
this.pendingSessions.push(session);
|
||||
session.on('close', this.eventSessionClose.bind(this, session));
|
||||
session.on('error', this.eventSessionError.bind(this, session));
|
||||
session.on('pdu', this.eventAnyPdu.bind(this, session));
|
||||
this.updateStatus();
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
private eventSessionConnected(session: any): void {
|
||||
this.logger.log1(`A client connected to center-${this.id}`);
|
||||
this.pendingSessions.push(session);
|
||||
session.on('close', this.eventSessionClose.bind(this, session));
|
||||
session.on('error', this.eventSessionError.bind(this, session));
|
||||
session.on('pdu', this.eventAnyPdu.bind(this, session));
|
||||
this.updateStatus();
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
|
||||
private eventSessionError(session: any): void {
|
||||
this.logger.log1(`A client encountered an error on center-${this.id}`);
|
||||
}
|
||||
private eventSessionError(session: any): void {
|
||||
this.logger.log1(`A client encountered an error on center-${this.id}`);
|
||||
}
|
||||
|
||||
private eventServerError(): void {
|
||||
this.logger.log1(`Center tried listening on port which is already in use, retrying in ${PORT_RELISTEN_DELAY}`);
|
||||
this.setStatus(0);
|
||||
setTimeout(this.doListen.bind(this), PORT_RELISTEN_DELAY);
|
||||
}
|
||||
private eventServerError(): void {
|
||||
this.logger.log1(`Center tried listening on port which is already in use, retrying in ${PORT_RELISTEN_DELAY}`);
|
||||
this.setStatus(0);
|
||||
setTimeout(this.doListen.bind(this), PORT_RELISTEN_DELAY);
|
||||
}
|
||||
|
||||
private eventSessionClose(session: any): void {
|
||||
this.logger.log1(`A client disconnected from center-${this.id}`);
|
||||
this.sessions = this.sessions.filter((s: any) => s !== session);
|
||||
this.nextSession = 0;
|
||||
this.pendingSessions = this.pendingSessions.filter((s: any) => s !== session);
|
||||
this.updateStatus();
|
||||
}
|
||||
private eventSessionClose(session: any): void {
|
||||
this.logger.log1(`A client disconnected from center-${this.id}`);
|
||||
this.sessions = this.sessions.filter((s: any) => s !== session);
|
||||
this.nextSession = 0;
|
||||
this.pendingSessions = this.pendingSessions.filter((s: any) => s !== session);
|
||||
this.updateStatus();
|
||||
}
|
||||
}
|
||||
|
@@ -6,15 +6,15 @@ import Center from "./Center";
|
||||
const CENTER_SESSIONS_FILE: string = process.env.CENTER_SESSIONS_FILE || "center_sessions.json";
|
||||
|
||||
export default class CenterSessionManager extends SessionManager {
|
||||
StorageFile: string = CENTER_SESSIONS_FILE
|
||||
ManagedSessionClass: typeof Center = Center;
|
||||
identifier: string = "Center";
|
||||
readonly logger: Logger = new Logger("CenterSessionManager");
|
||||
StorageFile: string = CENTER_SESSIONS_FILE
|
||||
ManagedSessionClass: typeof Center = Center;
|
||||
identifier: string = "Center";
|
||||
readonly logger: Logger = new Logger("CenterSessionManager");
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.setup();
|
||||
}
|
||||
constructor() {
|
||||
super();
|
||||
this.setup();
|
||||
}
|
||||
|
||||
comparatorFn: (arg: any, session: SmppSession) => boolean = (arg: any, session: SmppSession) => (session as Center).port === arg;
|
||||
comparatorFn: (arg: any, session: SmppSession) => boolean = (arg: any, session: SmppSession) => (session as Center).port === arg;
|
||||
}
|
@@ -13,271 +13,271 @@ const smpp = require("smpp");
|
||||
const AUTO_ENQUIRE_LINK_PERIOD: number = Number(process.env.AUTO_ENQUIRE_LINK_PERIOD) || 30000;
|
||||
|
||||
export default class Client extends SmppSession {
|
||||
readonly STATUSES: string[] = [
|
||||
"NOT CONNECTED",
|
||||
"CONNECTING",
|
||||
"CONNECTED",
|
||||
"BINDING",
|
||||
"BOUND",
|
||||
"BUSY",
|
||||
]
|
||||
url: string;
|
||||
_username: string;
|
||||
_password: string;
|
||||
_id: number;
|
||||
_status: string = this.STATUSES[0];
|
||||
readonly logger: Logger;
|
||||
private session?: any;
|
||||
private connectPromise: PersistentPromise | null = null;
|
||||
private bindPromise: PersistentPromise | null = null;
|
||||
private closePromise: PersistentPromise | null = null;
|
||||
readonly STATUSES: string[] = [
|
||||
"NOT CONNECTED",
|
||||
"CONNECTING",
|
||||
"CONNECTED",
|
||||
"BINDING",
|
||||
"BOUND",
|
||||
"BUSY",
|
||||
]
|
||||
url: string;
|
||||
_username: string;
|
||||
_password: string;
|
||||
_id: number;
|
||||
_status: string = this.STATUSES[0];
|
||||
readonly logger: Logger;
|
||||
private session?: any;
|
||||
private connectPromise: PersistentPromise | null = null;
|
||||
private bindPromise: PersistentPromise | null = null;
|
||||
private closePromise: PersistentPromise | null = null;
|
||||
|
||||
constructor(id: number, url: string, username: string, password: string) {
|
||||
super();
|
||||
this._id = id;
|
||||
this._username = username;
|
||||
this._password = password;
|
||||
this.url = url;
|
||||
constructor(id: number, url: string, username: string, password: string) {
|
||||
super();
|
||||
this._id = id;
|
||||
this._username = username;
|
||||
this._password = password;
|
||||
this.url = url;
|
||||
|
||||
this._defaultSingleJob = Job.createEmptySingle('submit_sm');
|
||||
this._defaultMultipleJob = Job.createEmptyMultiple('submit_sm');
|
||||
this._defaultSingleJob = Job.createEmptySingle('submit_sm');
|
||||
this._defaultMultipleJob = Job.createEmptyMultiple('submit_sm');
|
||||
|
||||
ProcessorManager.attachProcessors(this, ProcessorManager.getProcessors(DeliverSmReplyProcessor.name));
|
||||
ProcessorManager.attachProcessors(this, ProcessorManager.getProcessors(DeliverSmReplyProcessor.name));
|
||||
|
||||
this.logger = new Logger(`Client-${id}`);
|
||||
}
|
||||
this.logger = new Logger(`Client-${id}`);
|
||||
}
|
||||
|
||||
_defaultSingleJob: Job;
|
||||
_defaultSingleJob: Job;
|
||||
|
||||
get defaultSingleJob(): Job {
|
||||
return this._defaultSingleJob;
|
||||
}
|
||||
get defaultSingleJob(): Job {
|
||||
return this._defaultSingleJob;
|
||||
}
|
||||
|
||||
set defaultSingleJob(job: Job) {
|
||||
if (job.pdu && !job.pdu.command) {
|
||||
job.pdu.command = 'submit_sm';
|
||||
}
|
||||
super.defaultSingleJob = job;
|
||||
}
|
||||
set defaultSingleJob(job: Job) {
|
||||
if (job.pdu && !job.pdu.command) {
|
||||
job.pdu.command = 'submit_sm';
|
||||
}
|
||||
super.defaultSingleJob = job;
|
||||
}
|
||||
|
||||
_defaultMultipleJob: Job;
|
||||
_defaultMultipleJob: Job;
|
||||
|
||||
get defaultMultipleJob(): Job {
|
||||
return this._defaultMultipleJob;
|
||||
}
|
||||
get defaultMultipleJob(): Job {
|
||||
return this._defaultMultipleJob;
|
||||
}
|
||||
|
||||
set defaultMultipleJob(job: Job) {
|
||||
if (job.pdu && !job.pdu.command) {
|
||||
job.pdu.command = 'submit_sm';
|
||||
}
|
||||
super.defaultMultipleJob = job;
|
||||
}
|
||||
set defaultMultipleJob(job: Job) {
|
||||
if (job.pdu && !job.pdu.command) {
|
||||
job.pdu.command = 'submit_sm';
|
||||
}
|
||||
super.defaultMultipleJob = job;
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
}
|
||||
destroy(): void {
|
||||
}
|
||||
|
||||
doConnect(): PersistentPromise {
|
||||
this.connectPromise = new PersistentPromise((resolve, reject) => {
|
||||
if (this.status !== this.STATUSES[0]) {
|
||||
let errorString = `Client-${this.id} already connected`;
|
||||
this.logger.log1(errorString);
|
||||
reject(errorString);
|
||||
return;
|
||||
}
|
||||
doConnect(): PersistentPromise {
|
||||
this.connectPromise = new PersistentPromise((resolve, reject) => {
|
||||
if (this.status !== this.STATUSES[0]) {
|
||||
let errorString = `Client-${this.id} already connected`;
|
||||
this.logger.log1(errorString);
|
||||
reject(errorString);
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.log1(`Client-${this.id} connecting to ${this.url}`);
|
||||
this.setStatus(1);
|
||||
this.connectSession().then(resolve, ((err: any) => {
|
||||
this.logger.log1(`Client-${this.id} connection failed: ${err}`);
|
||||
this.setStatus(0);
|
||||
this.session.close();
|
||||
reject(err);
|
||||
}));
|
||||
});
|
||||
return this.connectPromise;
|
||||
}
|
||||
this.logger.log1(`Client-${this.id} connecting to ${this.url}`);
|
||||
this.setStatus(1);
|
||||
this.connectSession().then(resolve, ((err: any) => {
|
||||
this.logger.log1(`Client-${this.id} connection failed: ${err}`);
|
||||
this.setStatus(0);
|
||||
this.session.close();
|
||||
reject(err);
|
||||
}));
|
||||
});
|
||||
return this.connectPromise;
|
||||
}
|
||||
|
||||
doBind(): PersistentPromise {
|
||||
this.bindPromise = new PersistentPromise((resolve, reject) => {
|
||||
this.validateFields(reject);
|
||||
doBind(): PersistentPromise {
|
||||
this.bindPromise = new PersistentPromise((resolve, reject) => {
|
||||
this.validateFields(reject);
|
||||
|
||||
this.session.bind_transceiver({
|
||||
system_id: this.username,
|
||||
password: this.password,
|
||||
}, this.eventBindReply.bind(this));
|
||||
this.setStatus(3);
|
||||
});
|
||||
return this.bindPromise;
|
||||
}
|
||||
this.session.bind_transceiver({
|
||||
system_id: this.username,
|
||||
password: this.password,
|
||||
}, this.eventBindReply.bind(this));
|
||||
this.setStatus(3);
|
||||
});
|
||||
return this.bindPromise;
|
||||
}
|
||||
|
||||
connectAndBind(): Promise<void> {
|
||||
return this.doConnect().then(this.doBind.bind(this), (error) => {
|
||||
this.logger.log1(`Client-${this.id} connectAndBind failed: ${error}`);
|
||||
});
|
||||
}
|
||||
connectAndBind(): Promise<void> {
|
||||
return this.doConnect().then(this.doBind.bind(this), (error) => {
|
||||
this.logger.log1(`Client-${this.id} connectAndBind failed: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
postSerialize(obj: any): object {
|
||||
obj.url = this.url;
|
||||
return obj;
|
||||
}
|
||||
postSerialize(obj: any): object {
|
||||
obj.url = this.url;
|
||||
return obj;
|
||||
}
|
||||
|
||||
close(): Promise<void> {
|
||||
this.logger.log1(`Client-${this.id} closing connection`);
|
||||
if (this.session) {
|
||||
return Promise.resolve(this.session.close());
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
close(): Promise<void> {
|
||||
this.logger.log1(`Client-${this.id} closing connection`);
|
||||
if (this.session) {
|
||||
return Promise.resolve(this.session.close());
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
sendPdu(pdu: PDU, force?: boolean): Promise<object> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!force) {
|
||||
this.validateSession(reject);
|
||||
this.validateBound(reject);
|
||||
}
|
||||
// Is this expensive...?
|
||||
let pduCopy = new smpp.PDU(pdu.command, {...pdu});
|
||||
this.processors.Preprocessor.forEach((processor: PduProcessor) => processor.processPdu(this.session, pduCopy, this));
|
||||
this.logger.log5(`Client-${this.id} sending PDU: ${JSON.stringify(pduCopy)}`);
|
||||
this.doSendPdu(pduCopy, this.session).then((replyPdu: any) => {
|
||||
resolve(replyPdu);
|
||||
});
|
||||
});
|
||||
}
|
||||
sendPdu(pdu: PDU, force?: boolean): Promise<object> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!force) {
|
||||
this.validateSession(reject);
|
||||
this.validateBound(reject);
|
||||
}
|
||||
// Is this expensive...?
|
||||
let pduCopy = new smpp.PDU(pdu.command, {...pdu});
|
||||
this.processors.Preprocessor.forEach((processor: PduProcessor) => processor.processPdu(this.session, pduCopy, this));
|
||||
this.logger.log5(`Client-${this.id} sending PDU: ${JSON.stringify(pduCopy)}`);
|
||||
this.doSendPdu(pduCopy, this.session).then((replyPdu: any) => {
|
||||
resolve(replyPdu);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
sendMultiple(job: Job): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.validateSession(reject);
|
||||
this.validateBound(reject);
|
||||
if (!job.count || !job.perSecond) {
|
||||
reject(`Client-${this.id} sendMultiple failed: invalid job, missing fields`);
|
||||
}
|
||||
this.logger.log1(`Client-${this.id} sending multiple messages: ${JSON.stringify(job)}`);
|
||||
sendMultiple(job: Job): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.validateSession(reject);
|
||||
this.validateBound(reject);
|
||||
if (!job.count || !job.perSecond) {
|
||||
reject(`Client-${this.id} sendMultiple failed: invalid job, missing fields`);
|
||||
}
|
||||
this.logger.log1(`Client-${this.id} sending multiple messages: ${JSON.stringify(job)}`);
|
||||
|
||||
this.setStatus(4);
|
||||
this.setStatus(4);
|
||||
|
||||
let counter: number = 0;
|
||||
let previousUpdateCounter: number = 0;
|
||||
let counter: number = 0;
|
||||
let previousUpdateCounter: number = 0;
|
||||
|
||||
this.counterUpdateTimer.setInterval(() => {
|
||||
if (previousUpdateCounter !== counter) {
|
||||
this.eventEmitter.emit(this.EVENT.MESSAGE_SEND_COUNTER_UPDATE_EVENT, counter);
|
||||
previousUpdateCounter = counter;
|
||||
}
|
||||
}, '', `${this.MESSAGE_SEND_UPDATE_DELAY / 1000} s`);
|
||||
this.counterUpdateTimer.setInterval(() => {
|
||||
if (previousUpdateCounter !== counter) {
|
||||
this.eventEmitter.emit(this.EVENT.MESSAGE_SEND_COUNTER_UPDATE_EVENT, counter);
|
||||
previousUpdateCounter = counter;
|
||||
}
|
||||
}, '', `${this.MESSAGE_SEND_UPDATE_DELAY / 1000} s`);
|
||||
|
||||
let count: number = job.count || 1;
|
||||
let interval: number = 1 / (job.perSecond || 1);
|
||||
this.setStatus(5);
|
||||
this.sendTimer.setInterval(() => {
|
||||
if (count > 0 && counter >= count) {
|
||||
this.cancelSendInterval();
|
||||
} else {
|
||||
this.sendPdu(job.pdu, true)
|
||||
.catch(e => this.logger.log1(`Error sending message: ${e}`));
|
||||
counter++;
|
||||
}
|
||||
}, '', `${interval} s`);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
let count: number = job.count || 1;
|
||||
let interval: number = 1 / (job.perSecond || 1);
|
||||
this.setStatus(5);
|
||||
this.sendTimer.setInterval(() => {
|
||||
if (count > 0 && counter >= count) {
|
||||
this.cancelSendInterval();
|
||||
} else {
|
||||
this.sendPdu(job.pdu, true)
|
||||
.catch(e => this.logger.log1(`Error sending message: ${e}`));
|
||||
counter++;
|
||||
}
|
||||
}, '', `${interval} s`);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
private connectSession(): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
this.validateFields(reject);
|
||||
this.logger.log1(`Client-${this.id} connecting to ${this.url}`);
|
||||
private connectSession(): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
this.validateFields(reject);
|
||||
this.logger.log1(`Client-${this.id} connecting to ${this.url}`);
|
||||
|
||||
this.session = smpp.connect({
|
||||
url: this.url, auto_enquire_link_period: AUTO_ENQUIRE_LINK_PERIOD,
|
||||
}, this.eventSessionConnected.bind(this));
|
||||
this.session.on('error', this.eventSessionError.bind(this));
|
||||
this.session.on('close', this.eventSessionClose.bind(this));
|
||||
this.session.on('pdu', this.eventAnyPdu.bind(this, this.session));
|
||||
});
|
||||
}
|
||||
this.session = smpp.connect({
|
||||
url: this.url, auto_enquire_link_period: AUTO_ENQUIRE_LINK_PERIOD,
|
||||
}, this.eventSessionConnected.bind(this));
|
||||
this.session.on('error', this.eventSessionError.bind(this));
|
||||
this.session.on('close', this.eventSessionClose.bind(this));
|
||||
this.session.on('pdu', this.eventAnyPdu.bind(this, this.session));
|
||||
});
|
||||
}
|
||||
|
||||
private eventSessionConnected(): void {
|
||||
this.logger.log1(`Client-${this.id} connected to ${this.url}`);
|
||||
this.setStatus(2);
|
||||
if (this.connectPromise) {
|
||||
this.connectPromise.resolve();
|
||||
} else {
|
||||
this.logger.log1(`Client-${this.id} connected without connect promise`);
|
||||
}
|
||||
}
|
||||
private eventSessionConnected(): void {
|
||||
this.logger.log1(`Client-${this.id} connected to ${this.url}`);
|
||||
this.setStatus(2);
|
||||
if (this.connectPromise) {
|
||||
this.connectPromise.resolve();
|
||||
} else {
|
||||
this.logger.log1(`Client-${this.id} connected without connect promise`);
|
||||
}
|
||||
}
|
||||
|
||||
private eventSessionError(pdu: any): void {
|
||||
this.logger.log1(`Client-${this.id} error on ${this.url} - ${pdu.message}`);
|
||||
this.setStatus(0);
|
||||
this.rejectPromises();
|
||||
}
|
||||
private eventSessionError(pdu: any): void {
|
||||
this.logger.log1(`Client-${this.id} error on ${this.url} - ${pdu.message}`);
|
||||
this.setStatus(0);
|
||||
this.rejectPromises();
|
||||
}
|
||||
|
||||
private eventSessionClose(): void {
|
||||
this.logger.log1(`Client-${this.id} closed on ${this.url}`);
|
||||
this.setStatus(0);
|
||||
this.rejectPromises();
|
||||
}
|
||||
private eventSessionClose(): void {
|
||||
this.logger.log1(`Client-${this.id} closed on ${this.url}`);
|
||||
this.setStatus(0);
|
||||
this.rejectPromises();
|
||||
}
|
||||
|
||||
private eventBindReply(pdu: PDU): void {
|
||||
if (pdu.command_status === 0) {
|
||||
this.logger.log1(`Client-${this.id} bound to ${this.url}`);
|
||||
this.setStatus(4);
|
||||
if (this.bindPromise) {
|
||||
this.bindPromise.resolve();
|
||||
}
|
||||
} else {
|
||||
this.logger.log1(`Client-${this.id} bind failed to ${this.url}`);
|
||||
this.setStatus(2);
|
||||
if (this.bindPromise) {
|
||||
this.bindPromise.reject(pdu);
|
||||
}
|
||||
}
|
||||
}
|
||||
private eventBindReply(pdu: PDU): void {
|
||||
if (pdu.command_status === 0) {
|
||||
this.logger.log1(`Client-${this.id} bound to ${this.url}`);
|
||||
this.setStatus(4);
|
||||
if (this.bindPromise) {
|
||||
this.bindPromise.resolve();
|
||||
}
|
||||
} else {
|
||||
this.logger.log1(`Client-${this.id} bind failed to ${this.url}`);
|
||||
this.setStatus(2);
|
||||
if (this.bindPromise) {
|
||||
this.bindPromise.reject(pdu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private rejectPromises(err?: any): void {
|
||||
if (this.connectPromise) {
|
||||
this.connectPromise.reject(err);
|
||||
}
|
||||
if (this.bindPromise) {
|
||||
this.bindPromise.reject(err);
|
||||
}
|
||||
if (this.closePromise) {
|
||||
this.closePromise.resolve();
|
||||
}
|
||||
}
|
||||
private rejectPromises(err?: any): void {
|
||||
if (this.connectPromise) {
|
||||
this.connectPromise.reject(err);
|
||||
}
|
||||
if (this.bindPromise) {
|
||||
this.bindPromise.reject(err);
|
||||
}
|
||||
if (this.closePromise) {
|
||||
this.closePromise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
private validateFields(reject: (reason?: any) => void) {
|
||||
if (!this.url) {
|
||||
let error = `Client-${this.id} has no url set`;
|
||||
this.logger.log1(error);
|
||||
reject(error);
|
||||
}
|
||||
if (!this.username) {
|
||||
let error = `Client-${this.id} has no username set`;
|
||||
this.logger.log1(error);
|
||||
reject(error);
|
||||
}
|
||||
if (!this.password) {
|
||||
let error = `Client-${this.id} has no password set`;
|
||||
this.logger.log1(error);
|
||||
reject(error);
|
||||
}
|
||||
}
|
||||
private validateFields(reject: (reason?: any) => void) {
|
||||
if (!this.url) {
|
||||
let error = `Client-${this.id} has no url set`;
|
||||
this.logger.log1(error);
|
||||
reject(error);
|
||||
}
|
||||
if (!this.username) {
|
||||
let error = `Client-${this.id} has no username set`;
|
||||
this.logger.log1(error);
|
||||
reject(error);
|
||||
}
|
||||
if (!this.password) {
|
||||
let error = `Client-${this.id} has no password set`;
|
||||
this.logger.log1(error);
|
||||
reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
private validateSession(reject: (reason?: any) => void) {
|
||||
if (!this.session) {
|
||||
let errorMessage = `Client-${this.id} session is not defined`;
|
||||
this.logger.log1(errorMessage);
|
||||
reject(errorMessage);
|
||||
}
|
||||
}
|
||||
private validateSession(reject: (reason?: any) => void) {
|
||||
if (!this.session) {
|
||||
let errorMessage = `Client-${this.id} session is not defined`;
|
||||
this.logger.log1(errorMessage);
|
||||
reject(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private validateBound(reject: (reason?: any) => void) {
|
||||
if (this.status !== this.STATUSES[4]) {
|
||||
let errorMessage = `Client-${this.id} is not bound`;
|
||||
this.logger.log1(errorMessage);
|
||||
reject(errorMessage);
|
||||
}
|
||||
}
|
||||
private validateBound(reject: (reason?: any) => void) {
|
||||
if (this.status !== this.STATUSES[4]) {
|
||||
let errorMessage = `Client-${this.id} is not bound`;
|
||||
this.logger.log1(errorMessage);
|
||||
reject(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,15 +6,15 @@ import Client from "./Client";
|
||||
const CLIENT_SESSIONS_FILE: string = process.env.CLIENT_SESSIONS_FILE || "client_sessions.json";
|
||||
|
||||
export default class ClientSessionManager extends SessionManager {
|
||||
StorageFile: string = CLIENT_SESSIONS_FILE;
|
||||
ManagedSessionClass: typeof Client = Client;
|
||||
identifier: string = "Client";
|
||||
readonly logger: Logger = new Logger("ClientSessionManager");
|
||||
StorageFile: string = CLIENT_SESSIONS_FILE;
|
||||
ManagedSessionClass: typeof Client = Client;
|
||||
identifier: string = "Client";
|
||||
readonly logger: Logger = new Logger("ClientSessionManager");
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.setup();
|
||||
}
|
||||
constructor() {
|
||||
super();
|
||||
this.setup();
|
||||
}
|
||||
|
||||
comparatorFn: (arg: any, session: SmppSession) => boolean = (arg: any, session: SmppSession) => (session as Client).url === arg;
|
||||
comparatorFn: (arg: any, session: SmppSession) => boolean = (arg: any, session: SmppSession) => (session as Client).url === arg;
|
||||
}
|
@@ -1,37 +1,37 @@
|
||||
export type PDU = {
|
||||
command?: string;
|
||||
command_id?: number;
|
||||
command_length?: number;
|
||||
command_status?: number;
|
||||
data_coding?: number;
|
||||
dest_addr_npi?: number;
|
||||
dest_addr_ton?: number;
|
||||
destination_addr?: string;
|
||||
esm_class?: number,
|
||||
password?: string,
|
||||
priority_flag?: number,
|
||||
protocol_id?: number,
|
||||
registered_delivery?: number,
|
||||
replace_if_present_flag?: number,
|
||||
response?: (...args: any[]) => PDU,
|
||||
schedule_delivery_time?: string,
|
||||
sequence_number?: number,
|
||||
service_type?: string,
|
||||
short_message?: any,
|
||||
sm_default_msg_id?: number,
|
||||
source_addr?: string,
|
||||
source_addr_npi?: number,
|
||||
source_addr_ton?: number,
|
||||
system_id?: string,
|
||||
validity_period?: string
|
||||
command?: string;
|
||||
command_id?: number;
|
||||
command_length?: number;
|
||||
command_status?: number;
|
||||
data_coding?: number;
|
||||
dest_addr_npi?: number;
|
||||
dest_addr_ton?: number;
|
||||
destination_addr?: string;
|
||||
esm_class?: number,
|
||||
password?: string,
|
||||
priority_flag?: number,
|
||||
protocol_id?: number,
|
||||
registered_delivery?: number,
|
||||
replace_if_present_flag?: number,
|
||||
response?: (...args: any[]) => PDU,
|
||||
schedule_delivery_time?: string,
|
||||
sequence_number?: number,
|
||||
service_type?: string,
|
||||
short_message?: any,
|
||||
sm_default_msg_id?: number,
|
||||
source_addr?: string,
|
||||
source_addr_npi?: number,
|
||||
source_addr_ton?: number,
|
||||
system_id?: string,
|
||||
validity_period?: string
|
||||
};
|
||||
export type SerializedJob = {
|
||||
pdu: PDU;
|
||||
count?: number;
|
||||
perSecond?: number;
|
||||
pdu: PDU;
|
||||
count?: number;
|
||||
perSecond?: number;
|
||||
};
|
||||
export type WSMessage = {
|
||||
type: string;
|
||||
identifier: string;
|
||||
data?: any;
|
||||
type: string;
|
||||
identifier: string;
|
||||
data?: any;
|
||||
};
|
@@ -8,58 +8,58 @@ import SmppSession from "../SmppSession";
|
||||
import RequestHandler from "./RequestHandler";
|
||||
|
||||
export default class CenterRequestHandler extends RequestHandler {
|
||||
sessionManager: CenterSessionManager;
|
||||
logger: Logger = new Logger(this.constructor.name);
|
||||
sessionManager: CenterSessionManager;
|
||||
logger: Logger = new Logger(this.constructor.name);
|
||||
|
||||
constructor(sessionManager: SessionManager) {
|
||||
super();
|
||||
this.sessionManager = sessionManager as CenterSessionManager;
|
||||
}
|
||||
constructor(sessionManager: SessionManager) {
|
||||
super();
|
||||
this.sessionManager = sessionManager as CenterSessionManager;
|
||||
}
|
||||
|
||||
doGetAvailableProcessors(req: any, res: any): void {
|
||||
this.logger.log1("Getting available processors");
|
||||
let processors: PduProcessor[] = ProcessorManager.getProcessorsForType(Center.name);
|
||||
res.send(processors.map((processor: any) => processor.serialize()));
|
||||
}
|
||||
doGetAvailableProcessors(req: any, res: any): void {
|
||||
this.logger.log1("Getting available processors");
|
||||
let processors: PduProcessor[] = ProcessorManager.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.appliedProcessors;
|
||||
res.send(processors.map((processor: any) => processor.serialize()));
|
||||
}, this.handleSessionNotFound.bind(this, req, res));
|
||||
}
|
||||
doGetAppliedProcessors(req: any, res: any): void {
|
||||
this.sessionManager.getSession(req.params.id).then((session: SmppSession) => {
|
||||
let processors: PduProcessor[] = session.appliedProcessors;
|
||||
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 processors: PduProcessor[] = ProcessorManager.getProcessors(req.body.name);
|
||||
ProcessorManager.attachProcessors(session, processors);
|
||||
res.send(session.serialize());
|
||||
}, this.handleSessionNotFound.bind(this, req, res));
|
||||
}
|
||||
doAddProcessor(req: any, res: any): void {
|
||||
this.sessionManager.getSession(req.params.id).then((session: SmppSession) => {
|
||||
let processors: PduProcessor[] = ProcessorManager.getProcessors(req.body.name);
|
||||
ProcessorManager.attachProcessors(session, processors);
|
||||
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 processors: PduProcessor[] = ProcessorManager.getProcessors(req.body.name);
|
||||
ProcessorManager.detachProcessors(session, processors);
|
||||
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 processors: PduProcessor[] = ProcessorManager.getProcessors(req.body.name);
|
||||
ProcessorManager.detachProcessors(session, processors);
|
||||
res.send(session.serialize());
|
||||
}, this.handleSessionNotFound.bind(this, req, res));
|
||||
}
|
||||
|
||||
doPost(req: any, res: any): void {
|
||||
this.logger.log1("Creating center 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 center session: ${err}`);
|
||||
res.status(500).send();
|
||||
});
|
||||
}
|
||||
doPost(req: any, res: any): void {
|
||||
this.logger.log1("Creating center 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 center session: ${err}`);
|
||||
res.status(500).send();
|
||||
});
|
||||
}
|
||||
|
||||
doConnect(req: any, res: any): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
doConnect(req: any, res: any): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
doBind(req: any, res: any): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
doBind(req: any, res: any): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
||||
|
@@ -8,76 +8,76 @@ import SmppSession from "../SmppSession";
|
||||
import RequestHandler from "./RequestHandler";
|
||||
|
||||
export default class ClientRequestHandler extends RequestHandler {
|
||||
sessionManager: ClientSessionManager;
|
||||
logger: Logger = new Logger(this.constructor.name);
|
||||
sessionManager: ClientSessionManager;
|
||||
logger: Logger = new Logger(this.constructor.name);
|
||||
|
||||
constructor(sessionManager: SessionManager) {
|
||||
super();
|
||||
this.sessionManager = sessionManager as ClientSessionManager;
|
||||
}
|
||||
constructor(sessionManager: SessionManager) {
|
||||
super();
|
||||
this.sessionManager = sessionManager as ClientSessionManager;
|
||||
}
|
||||
|
||||
doGetAvailableProcessors(req: any, res: any): void {
|
||||
this.logger.log1("Getting available processors");
|
||||
let processors: PduProcessor[] = ProcessorManager.getProcessorsForType(Client.name);
|
||||
res.send(processors.map((processor: any) => processor.serialize()));
|
||||
}
|
||||
doGetAvailableProcessors(req: any, res: any): void {
|
||||
this.logger.log1("Getting available processors");
|
||||
let processors: PduProcessor[] = ProcessorManager.getProcessorsForType(Client.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.appliedProcessors;
|
||||
res.send(processors.map((processor: any) => processor.serialize()));
|
||||
}, this.handleSessionNotFound.bind(this, req, res));
|
||||
}
|
||||
doGetAppliedProcessors(req: any, res: any): void {
|
||||
this.sessionManager.getSession(req.params.id).then((session: SmppSession) => {
|
||||
let processors: PduProcessor[] = session.appliedProcessors;
|
||||
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 processors: PduProcessor[] = ProcessorManager.getProcessors(req.body.name);
|
||||
ProcessorManager.attachProcessors(session, processors);
|
||||
res.send(session.serialize());
|
||||
}, this.handleSessionNotFound.bind(this, req, res));
|
||||
}
|
||||
doAddProcessor(req: any, res: any): void {
|
||||
this.sessionManager.getSession(req.params.id).then((session: SmppSession) => {
|
||||
let processors: PduProcessor[] = ProcessorManager.getProcessors(req.body.name);
|
||||
ProcessorManager.attachProcessors(session, processors);
|
||||
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 processors: PduProcessor[] = ProcessorManager.getProcessors(req.body.name);
|
||||
ProcessorManager.detachProcessors(session, processors);
|
||||
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 processors: PduProcessor[] = ProcessorManager.getProcessors(req.body.name);
|
||||
ProcessorManager.detachProcessors(session, processors);
|
||||
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.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();
|
||||
});
|
||||
}
|
||||
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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@@ -8,79 +8,81 @@ const express = require("express");
|
||||
const bodyParser = require("body-parser");
|
||||
const compression = require("compression");
|
||||
const zlib = require("zlib");
|
||||
const cors = require("cors");
|
||||
|
||||
const SERVER_PORT: number = Number(process.env.SERVER_PORT) || 8190;
|
||||
|
||||
export default class HttpServer {
|
||||
private readonly clientRequestHandler: RequestHandler;
|
||||
private readonly centerRequestHandler: RequestHandler;
|
||||
private readonly clientRequestHandler: RequestHandler;
|
||||
private readonly centerRequestHandler: RequestHandler;
|
||||
|
||||
private app: any;
|
||||
private server: any;
|
||||
private readonly logger: Logger = new Logger(this.constructor.name);
|
||||
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);
|
||||
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 = express();
|
||||
this.app.use(cors());
|
||||
this.app.use(bodyParser.json());
|
||||
|
||||
this.app.use(compression({
|
||||
level: 9,
|
||||
strategy: zlib.constants.BROTLI_MODE_TEXT,
|
||||
}));
|
||||
this.app.use(compression({
|
||||
level: 9,
|
||||
strategy: zlib.constants.BROTLI_MODE_TEXT,
|
||||
}));
|
||||
|
||||
let clientApiPath: string = 'ClientEntity';
|
||||
let centerApiPath: string = 'CenterEntity';
|
||||
let clientApiPath: string = 'ClientEntity';
|
||||
let centerApiPath: string = 'CenterEntity';
|
||||
|
||||
this.app.get(`/api/${clientApiPath}`, this.clientRequestHandler.doGet.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}`, this.clientRequestHandler.doPost.bind(this.clientRequestHandler));
|
||||
this.app.put(`/api/${clientApiPath}/:id/send`, this.clientRequestHandler.doConfigureSingleJob.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/send/default`, this.clientRequestHandler.doSendSingleJob.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/send`, this.clientRequestHandler.doSend.bind(this.clientRequestHandler));
|
||||
this.app.put(`/api/${clientApiPath}/:id/sendMany`, this.clientRequestHandler.doConfigureManyJob.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/sendMany/default`, this.clientRequestHandler.doSendManyJob.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/sendMany`, this.clientRequestHandler.doSendMany.bind(this.clientRequestHandler));
|
||||
this.app.delete(`/api/${clientApiPath}/:id/sendMany`, this.clientRequestHandler.doCancelSendMany.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/bind`, this.clientRequestHandler.doBind.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/connect`, this.clientRequestHandler.doConnect.bind(this.clientRequestHandler));
|
||||
this.app.delete(`/api/${clientApiPath}/:id/connect`, this.clientRequestHandler.doDisconnect.bind(this.clientRequestHandler));
|
||||
this.app.get(`/api/${clientApiPath}/processors`, this.clientRequestHandler.doGetAvailableProcessors.bind(this.clientRequestHandler));
|
||||
this.app.get(`/api/${clientApiPath}/:id/processors`, this.clientRequestHandler.doGetAppliedProcessors.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/processors`, this.clientRequestHandler.doAddProcessor.bind(this.clientRequestHandler));
|
||||
this.app.delete(`/api/${clientApiPath}/:id/processors`, this.clientRequestHandler.doRemoveProcessor.bind(this.clientRequestHandler));
|
||||
this.app.get(`/api/${clientApiPath}`, this.clientRequestHandler.doGet.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}`, this.clientRequestHandler.doPost.bind(this.clientRequestHandler));
|
||||
this.app.put(`/api/${clientApiPath}/:id/send`, this.clientRequestHandler.doConfigureSingleJob.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/send/default`, this.clientRequestHandler.doSendSingleJob.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/send`, this.clientRequestHandler.doSend.bind(this.clientRequestHandler));
|
||||
this.app.put(`/api/${clientApiPath}/:id/sendMany`, this.clientRequestHandler.doConfigureManyJob.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/sendMany/default`, this.clientRequestHandler.doSendManyJob.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/sendMany`, this.clientRequestHandler.doSendMany.bind(this.clientRequestHandler));
|
||||
this.app.delete(`/api/${clientApiPath}/:id/sendMany`, this.clientRequestHandler.doCancelSendMany.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/bind`, this.clientRequestHandler.doBind.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/connect`, this.clientRequestHandler.doConnect.bind(this.clientRequestHandler));
|
||||
this.app.delete(`/api/${clientApiPath}/:id/connect`, this.clientRequestHandler.doDisconnect.bind(this.clientRequestHandler));
|
||||
this.app.get(`/api/${clientApiPath}/processors`, this.clientRequestHandler.doGetAvailableProcessors.bind(this.clientRequestHandler));
|
||||
this.app.get(`/api/${clientApiPath}/:id/processors`, this.clientRequestHandler.doGetAppliedProcessors.bind(this.clientRequestHandler));
|
||||
this.app.post(`/api/${clientApiPath}/:id/processors`, this.clientRequestHandler.doAddProcessor.bind(this.clientRequestHandler));
|
||||
this.app.delete(`/api/${clientApiPath}/:id/processors`, this.clientRequestHandler.doRemoveProcessor.bind(this.clientRequestHandler));
|
||||
|
||||
this.app.get(`/api/${clientApiPath}/:id`, this.clientRequestHandler.doGetById.bind(this.clientRequestHandler));
|
||||
this.app.patch(`/api/${clientApiPath}/:id`, this.clientRequestHandler.doPatch.bind(this.clientRequestHandler));
|
||||
this.app.delete(`/api/${clientApiPath}/:id`, this.clientRequestHandler.doDelete.bind(this.clientRequestHandler));
|
||||
this.app.get(`/api/${clientApiPath}/:id`, this.clientRequestHandler.doGetById.bind(this.clientRequestHandler));
|
||||
this.app.patch(`/api/${clientApiPath}/:id`, this.clientRequestHandler.doPatch.bind(this.clientRequestHandler));
|
||||
this.app.delete(`/api/${clientApiPath}/:id`, this.clientRequestHandler.doDelete.bind(this.clientRequestHandler));
|
||||
|
||||
this.app.get(`/api/${centerApiPath}`, this.centerRequestHandler.doGet.bind(this.centerRequestHandler));
|
||||
this.app.post(`/api/${centerApiPath}`, this.centerRequestHandler.doPost.bind(this.centerRequestHandler));
|
||||
this.app.put(`/api/${centerApiPath}/:id/send`, this.centerRequestHandler.doConfigureSingleJob.bind(this.centerRequestHandler));
|
||||
this.app.post(`/api/${centerApiPath}/:id/send/default`, this.centerRequestHandler.doSendSingleJob.bind(this.centerRequestHandler));
|
||||
this.app.post(`/api/${centerApiPath}/:id/send`, this.centerRequestHandler.doSend.bind(this.centerRequestHandler));
|
||||
this.app.put(`/api/${centerApiPath}/:id/sendMany`, this.centerRequestHandler.doConfigureManyJob.bind(this.centerRequestHandler));
|
||||
this.app.post(`/api/${centerApiPath}/:id/sendMany/default`, this.centerRequestHandler.doSendManyJob.bind(this.centerRequestHandler));
|
||||
this.app.post(`/api/${centerApiPath}/:id/sendMany`, this.centerRequestHandler.doSendMany.bind(this.centerRequestHandler));
|
||||
this.app.delete(`/api/${centerApiPath}/:id/sendMany`, this.centerRequestHandler.doCancelSendMany.bind(this.centerRequestHandler));
|
||||
this.app.delete(`/api/${centerApiPath}/:id/connect`, this.centerRequestHandler.doDisconnect.bind(this.centerRequestHandler));
|
||||
this.app.get(`/api/${centerApiPath}/processors`, this.centerRequestHandler.doGetAvailableProcessors.bind(this.centerRequestHandler));
|
||||
this.app.get(`/api/${centerApiPath}/:id/processors`, this.centerRequestHandler.doGetAppliedProcessors.bind(this.centerRequestHandler));
|
||||
this.app.post(`/api/${centerApiPath}/:id/processors`, this.centerRequestHandler.doAddProcessor.bind(this.centerRequestHandler));
|
||||
this.app.delete(`/api/${centerApiPath}/:id/processors`, this.centerRequestHandler.doRemoveProcessor.bind(this.centerRequestHandler));
|
||||
this.app.get(`/api/${centerApiPath}`, this.centerRequestHandler.doGet.bind(this.centerRequestHandler));
|
||||
this.app.post(`/api/${centerApiPath}`, this.centerRequestHandler.doPost.bind(this.centerRequestHandler));
|
||||
this.app.put(`/api/${centerApiPath}/:id/send`, this.centerRequestHandler.doConfigureSingleJob.bind(this.centerRequestHandler));
|
||||
this.app.post(`/api/${centerApiPath}/:id/send/default`, this.centerRequestHandler.doSendSingleJob.bind(this.centerRequestHandler));
|
||||
this.app.post(`/api/${centerApiPath}/:id/send`, this.centerRequestHandler.doSend.bind(this.centerRequestHandler));
|
||||
this.app.put(`/api/${centerApiPath}/:id/sendMany`, this.centerRequestHandler.doConfigureManyJob.bind(this.centerRequestHandler));
|
||||
this.app.post(`/api/${centerApiPath}/:id/sendMany/default`, this.centerRequestHandler.doSendManyJob.bind(this.centerRequestHandler));
|
||||
this.app.post(`/api/${centerApiPath}/:id/sendMany`, this.centerRequestHandler.doSendMany.bind(this.centerRequestHandler));
|
||||
this.app.delete(`/api/${centerApiPath}/:id/sendMany`, this.centerRequestHandler.doCancelSendMany.bind(this.centerRequestHandler));
|
||||
this.app.delete(`/api/${centerApiPath}/:id/connect`, this.centerRequestHandler.doDisconnect.bind(this.centerRequestHandler));
|
||||
this.app.get(`/api/${centerApiPath}/processors`, this.centerRequestHandler.doGetAvailableProcessors.bind(this.centerRequestHandler));
|
||||
this.app.get(`/api/${centerApiPath}/:id/processors`, this.centerRequestHandler.doGetAppliedProcessors.bind(this.centerRequestHandler));
|
||||
this.app.post(`/api/${centerApiPath}/:id/processors`, this.centerRequestHandler.doAddProcessor.bind(this.centerRequestHandler));
|
||||
this.app.delete(`/api/${centerApiPath}/:id/processors`, this.centerRequestHandler.doRemoveProcessor.bind(this.centerRequestHandler));
|
||||
|
||||
this.app.get(`/api/${centerApiPath}/:id`, this.centerRequestHandler.doGetById.bind(this.centerRequestHandler));
|
||||
this.app.patch(`/api/${centerApiPath}/:id`, this.centerRequestHandler.doPatch.bind(this.centerRequestHandler));
|
||||
this.app.delete(`/api/${centerApiPath}/:id`, this.centerRequestHandler.doDelete.bind(this.centerRequestHandler));
|
||||
this.app.get(`/api/${centerApiPath}/:id`, this.centerRequestHandler.doGetById.bind(this.centerRequestHandler));
|
||||
this.app.patch(`/api/${centerApiPath}/:id`, this.centerRequestHandler.doPatch.bind(this.centerRequestHandler));
|
||||
this.app.delete(`/api/${centerApiPath}/:id`, this.centerRequestHandler.doDelete.bind(this.centerRequestHandler));
|
||||
|
||||
this.app.get('/api/ping', function (req: any, res: any) {
|
||||
res.send('pong');
|
||||
});
|
||||
this.app.get('/api/ping', function (req: any, res: any) {
|
||||
res.send('pong');
|
||||
});
|
||||
|
||||
this.server = this.app.listen(SERVER_PORT, function () {
|
||||
// @ts-ignore
|
||||
this.logger.log1(`HTTPServer listening at http://localhost:${SERVER_PORT}`)
|
||||
}.bind(this));
|
||||
}
|
||||
this.server = this.app.listen(SERVER_PORT, function () {
|
||||
// @ts-ignore
|
||||
this.logger.log1(`HTTPServer listening at http://localhost:${SERVER_PORT}`)
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
|
@@ -4,156 +4,156 @@ import SessionManager from "../SessionManager";
|
||||
import SmppSession from "../SmppSession";
|
||||
|
||||
export default abstract class RequestHandler {
|
||||
abstract sessionManager: SessionManager;
|
||||
logger: Logger = new Logger(this.constructor.name);
|
||||
abstract sessionManager: SessionManager;
|
||||
logger: Logger = new Logger(this.constructor.name);
|
||||
|
||||
doGet(req: any, res: any): void {
|
||||
this.logger.log1(`Getting sessions`);
|
||||
res.send(this.sessionManager.serialize());
|
||||
}
|
||||
doGet(req: any, res: any): void {
|
||||
this.logger.log1(`Getting sessions`);
|
||||
res.send(this.sessionManager.serialize());
|
||||
}
|
||||
|
||||
doGetById(req: any, res: any): void {
|
||||
this.sessionManager.getSession(req.params.id).then((session: SmppSession) => {
|
||||
this.logger.log1(`Session found with ID ${req.params.id}`)
|
||||
res.send(session.serialize());
|
||||
}, this.handleSessionNotFound.bind(this, req, res));
|
||||
}
|
||||
doGetById(req: any, res: any): void {
|
||||
this.sessionManager.getSession(req.params.id).then((session: SmppSession) => {
|
||||
this.logger.log1(`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.username = req.body.username;
|
||||
}
|
||||
if (!!req.body.password && req.body.password !== session.password) {
|
||||
session.password = req.body.password;
|
||||
}
|
||||
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.username = req.body.username;
|
||||
}
|
||||
if (!!req.body.password && req.body.password !== session.password) {
|
||||
session.password = req.body.password;
|
||||
}
|
||||
res.send(session.serialize());
|
||||
}, this.handleSessionNotFound.bind(this, req, res));
|
||||
}
|
||||
|
||||
doConfigureSingleJob(req: any, res: any): void {
|
||||
this.sessionManager.getSession(Number(req.params.id)).then((session: SmppSession) => {
|
||||
let job: Job = session.defaultSingleJob;
|
||||
job.update(req);
|
||||
this.logger.log1(`Updating default job on session with ID ${req.params.id}`);
|
||||
res.send(session.serialize());
|
||||
}, this.handleSessionNotFound.bind(this, req, res));
|
||||
}
|
||||
doConfigureSingleJob(req: any, res: any): void {
|
||||
this.sessionManager.getSession(Number(req.params.id)).then((session: SmppSession) => {
|
||||
let job: Job = session.defaultSingleJob;
|
||||
job.update(req);
|
||||
this.logger.log1(`Updating default job on session with ID ${req.params.id}`);
|
||||
res.send(session.serialize());
|
||||
}, 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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
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 job: Job = session.defaultMultipleJob;
|
||||
job.update(req);
|
||||
this.logger.log1(`Updating default job on session with ID ${req.params.id}`);
|
||||
res.send(session.serialize());
|
||||
}, this.handleSessionNotFound.bind(this, req, res));
|
||||
}
|
||||
doConfigureManyJob(req: any, res: any): void {
|
||||
this.sessionManager.getSession(req.params.id).then((session: SmppSession) => {
|
||||
let job: Job = session.defaultMultipleJob;
|
||||
job.update(req);
|
||||
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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
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();
|
||||
res.send({});
|
||||
}, 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();
|
||||
res.send({});
|
||||
}, 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));
|
||||
}
|
||||
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.logger.log1(`Deleting session with ID ${req.params.id}`);
|
||||
this.sessionManager.removeSession(session);
|
||||
res.send({});
|
||||
}, this.handleSessionNotFound.bind(this, req, res));
|
||||
}
|
||||
doDelete(req: any, res: any) {
|
||||
this.sessionManager.getSession(req.params.id).then((session: SmppSession) => {
|
||||
this.logger.log1(`Deleting session with ID ${req.params.id}`);
|
||||
this.sessionManager.removeSession(session);
|
||||
res.send({});
|
||||
}, this.handleSessionNotFound.bind(this, req, res));
|
||||
}
|
||||
|
||||
abstract doPost(req: any, res: any): void;
|
||||
abstract doPost(req: any, res: any): void;
|
||||
|
||||
abstract doConnect(req: any, res: any): void;
|
||||
abstract doConnect(req: any, res: any): void;
|
||||
|
||||
abstract doBind(req: any, res: any): void;
|
||||
abstract doBind(req: any, res: any): void;
|
||||
|
||||
abstract doGetAvailableProcessors(req: any, res: any): void;
|
||||
abstract doGetAvailableProcessors(req: any, res: any): void;
|
||||
|
||||
abstract doGetAppliedProcessors(req: any, res: any): void;
|
||||
abstract doGetAppliedProcessors(req: any, res: any): void;
|
||||
|
||||
abstract doAddProcessor(req: any, res: any): void;
|
||||
abstract doAddProcessor(req: any, res: any): void;
|
||||
|
||||
abstract doRemoveProcessor(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
|
||||
});
|
||||
}
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
162
src/Job/Job.ts
162
src/Job/Job.ts
@@ -4,102 +4,102 @@ import {PDU, SerializedJob} from "../CommonObjects";
|
||||
const smpp = require("smpp");
|
||||
|
||||
export default class Job {
|
||||
static readonly STATE_CHANGED: string = "STATE_CHANGED";
|
||||
private eventEmitter: EventEmitter = new EventEmitter();
|
||||
static readonly STATE_CHANGED: string = "STATE_CHANGED";
|
||||
private eventEmitter: EventEmitter = new EventEmitter();
|
||||
|
||||
constructor(pdu: PDU, perSecond?: number, count?: number) {
|
||||
Job.pduParseShortMessage(pdu);
|
||||
this._pdu = pdu;
|
||||
this._perSecond = perSecond;
|
||||
this._count = count;
|
||||
}
|
||||
constructor(pdu: PDU, perSecond?: number, count?: number) {
|
||||
Job.pduParseShortMessage(pdu);
|
||||
this._pdu = pdu;
|
||||
this._perSecond = perSecond;
|
||||
this._count = count;
|
||||
}
|
||||
|
||||
private _pdu: PDU;
|
||||
private _pdu: PDU;
|
||||
|
||||
get pdu(): PDU {
|
||||
return this._pdu;
|
||||
}
|
||||
get pdu(): PDU {
|
||||
return this._pdu;
|
||||
}
|
||||
|
||||
set pdu(value: PDU) {
|
||||
this._pdu = value;
|
||||
this.eventEmitter.emit(Job.STATE_CHANGED, {});
|
||||
}
|
||||
set pdu(value: PDU) {
|
||||
this._pdu = value;
|
||||
this.eventEmitter.emit(Job.STATE_CHANGED, {});
|
||||
}
|
||||
|
||||
private _perSecond?: number;
|
||||
private _perSecond?: number;
|
||||
|
||||
get perSecond(): number {
|
||||
return <number>this._perSecond;
|
||||
}
|
||||
get perSecond(): number {
|
||||
return <number>this._perSecond;
|
||||
}
|
||||
|
||||
set perSecond(value: number) {
|
||||
this._perSecond = value;
|
||||
this.eventEmitter.emit(Job.STATE_CHANGED, {});
|
||||
}
|
||||
set perSecond(value: number) {
|
||||
this._perSecond = value;
|
||||
this.eventEmitter.emit(Job.STATE_CHANGED, {});
|
||||
}
|
||||
|
||||
private _count?: number;
|
||||
private _count?: number;
|
||||
|
||||
get count(): number {
|
||||
return <number>this._count;
|
||||
}
|
||||
get count(): number {
|
||||
return <number>this._count;
|
||||
}
|
||||
|
||||
set count(value: number) {
|
||||
this._count = value;
|
||||
this.eventEmitter.emit(Job.STATE_CHANGED, {});
|
||||
}
|
||||
set count(value: number) {
|
||||
this._count = value;
|
||||
this.eventEmitter.emit(Job.STATE_CHANGED, {});
|
||||
}
|
||||
|
||||
static pduParseShortMessage(pdu: PDU) {
|
||||
if (pdu.short_message && pdu.short_message.type === "Buffer") {
|
||||
pdu.short_message = Buffer.from(pdu.short_message.data, 'ascii').toString();
|
||||
}
|
||||
if (typeof pdu.short_message === "object") {
|
||||
pdu.short_message = pdu.short_message.toString();
|
||||
}
|
||||
}
|
||||
static pduParseShortMessage(pdu: PDU) {
|
||||
if (pdu.short_message && pdu.short_message.type === "Buffer") {
|
||||
pdu.short_message = Buffer.from(pdu.short_message.data, 'ascii').toString();
|
||||
}
|
||||
if (typeof pdu.short_message === "object") {
|
||||
pdu.short_message = pdu.short_message.toString();
|
||||
}
|
||||
}
|
||||
|
||||
static createEmptySingle(command: string): Job {
|
||||
let pdu1 = new smpp.PDU(command, {});
|
||||
Job.pduParseShortMessage(pdu1);
|
||||
return new Job(pdu1);
|
||||
}
|
||||
static createEmptySingle(command: string): Job {
|
||||
let pdu1 = new smpp.PDU(command, {});
|
||||
Job.pduParseShortMessage(pdu1);
|
||||
return new Job(pdu1);
|
||||
}
|
||||
|
||||
static createEmptyMultiple(command: string): Job {
|
||||
let pdu1 = new smpp.PDU(command, {});
|
||||
Job.pduParseShortMessage(pdu1);
|
||||
return new Job(pdu1, 1, 1);
|
||||
}
|
||||
static createEmptyMultiple(command: string): Job {
|
||||
let pdu1 = new smpp.PDU(command, {});
|
||||
Job.pduParseShortMessage(pdu1);
|
||||
return new Job(pdu1, 1, 1);
|
||||
}
|
||||
|
||||
static deserialize(serialized: SerializedJob): Job {
|
||||
let pdu: PDU = new smpp.PDU(serialized.pdu.command, serialized.pdu);
|
||||
return new Job(pdu, serialized.perSecond, serialized.count);
|
||||
}
|
||||
static deserialize(serialized: SerializedJob): Job {
|
||||
let pdu: PDU = new smpp.PDU(serialized.pdu.command, serialized.pdu);
|
||||
return new Job(pdu, serialized.perSecond, serialized.count);
|
||||
}
|
||||
|
||||
update(req: any): void {
|
||||
if (req.body.source != this._pdu.source_addr) {
|
||||
this._pdu.source_addr = req.body.source;
|
||||
}
|
||||
if (req.body.destination != this._pdu.destination_addr) {
|
||||
this._pdu.destination_addr = req.body.destination;
|
||||
}
|
||||
if (req.body.message != this._pdu.short_message) {
|
||||
this._pdu.short_message = req.body.message;
|
||||
}
|
||||
if (!!this._perSecond && !!req.body.perSecond && req.body.perSecond != this._perSecond) {
|
||||
this._perSecond = req.body.perSecond;
|
||||
}
|
||||
if (!!this._count && !!req.body.count && req.body.count != this._count) {
|
||||
this._count = req.body.count;
|
||||
}
|
||||
}
|
||||
update(req: any): void {
|
||||
if (req.body.source != this._pdu.source_addr) {
|
||||
this._pdu.source_addr = req.body.source;
|
||||
}
|
||||
if (req.body.destination != this._pdu.destination_addr) {
|
||||
this._pdu.destination_addr = req.body.destination;
|
||||
}
|
||||
if (req.body.message != this._pdu.short_message) {
|
||||
this._pdu.short_message = req.body.message;
|
||||
}
|
||||
if (!!this._perSecond && !!req.body.perSecond && req.body.perSecond != this._perSecond) {
|
||||
this._perSecond = req.body.perSecond;
|
||||
}
|
||||
if (!!this._count && !!req.body.count && req.body.count != this._count) {
|
||||
this._count = req.body.count;
|
||||
}
|
||||
}
|
||||
|
||||
serialize(): SerializedJob {
|
||||
return {
|
||||
pdu: this.pdu,
|
||||
perSecond: this.perSecond,
|
||||
count: this.count
|
||||
};
|
||||
}
|
||||
serialize(): SerializedJob {
|
||||
return {
|
||||
pdu: this.pdu,
|
||||
perSecond: this.perSecond,
|
||||
count: this.count
|
||||
};
|
||||
}
|
||||
|
||||
on(event: string, callback: (...args: any[]) => void): void {
|
||||
this.eventEmitter.on(event, callback);
|
||||
}
|
||||
on(event: string, callback: (...args: any[]) => void): void {
|
||||
this.eventEmitter.on(event, callback);
|
||||
}
|
||||
}
|
102
src/Logger.ts
102
src/Logger.ts
@@ -6,63 +6,63 @@ const LOG_LEVEL: number = Number(process.env.LOG_LEVEL) || 0;
|
||||
const LOG_FILE: string = process.env.LOG_FILE || "";
|
||||
|
||||
export default class Logger {
|
||||
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);
|
||||
private clazz: string;
|
||||
private readonly logLevel: number;
|
||||
private readonly logFile: string;
|
||||
private readonly logFileWriteStream: WriteStream | null = null;
|
||||
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);
|
||||
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;
|
||||
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'});
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
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();
|
||||
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 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 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 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");
|
||||
}
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,17 +1,17 @@
|
||||
import {PDU} from "./CommonObjects";
|
||||
|
||||
export default class MessageIdManager {
|
||||
private static messages: { [key: string]: number } = {};
|
||||
private static messages: { [key: string]: number } = {};
|
||||
|
||||
static addMessageId(message: PDU, id: number): void {
|
||||
this.messages[this.getMessageHash(message)] = id;
|
||||
}
|
||||
static addMessageId(message: PDU, id: number): void {
|
||||
this.messages[this.getMessageHash(message)] = id;
|
||||
}
|
||||
|
||||
static getMessageId(message: PDU): number | undefined {
|
||||
return this.messages[this.getMessageHash(message)];
|
||||
}
|
||||
static getMessageId(message: PDU): number | undefined {
|
||||
return this.messages[this.getMessageHash(message)];
|
||||
}
|
||||
|
||||
private static getMessageHash(message: PDU): string {
|
||||
return btoa(`${message.source_addr}:${message.destination_addr}:${message.short_message}`);
|
||||
}
|
||||
private static getMessageHash(message: PDU): string {
|
||||
return btoa(`${message.source_addr}:${message.destination_addr}:${message.short_message}`);
|
||||
}
|
||||
}
|
@@ -2,36 +2,36 @@ import Logger from "../Logger";
|
||||
import SmppSession from "../SmppSession";
|
||||
|
||||
export default abstract class PduProcessor {
|
||||
readonly abstract type: string
|
||||
readonly sessionType: string;
|
||||
readonly name: string = this.constructor.name;
|
||||
readonly logger: Logger = new Logger(`PduProcessor: ${this.name}`);
|
||||
abstract applicableCommands: string[];
|
||||
readonly abstract type: string
|
||||
readonly sessionType: string;
|
||||
readonly name: string = this.constructor.name;
|
||||
readonly logger: Logger = new Logger(`PduProcessor: ${this.name}`);
|
||||
abstract applicableCommands: string[];
|
||||
|
||||
constructor(type: string) {
|
||||
this.sessionType = type;
|
||||
}
|
||||
constructor(type: string) {
|
||||
this.sessionType = type;
|
||||
}
|
||||
|
||||
protected pduDoesApply(pdu: any): boolean {
|
||||
if (pdu.command) {
|
||||
return this.applicableCommands.includes(pdu.command);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
processPdu(session: any, pdu: any, entity?: SmppSession | undefined): any {
|
||||
if (this.pduDoesApply(pdu)) {
|
||||
return this.doProcess(session, pdu, entity);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract doProcess(session: any, pdu: any, entity?: SmppSession | undefined): any;
|
||||
serialize(): object {
|
||||
return {
|
||||
servesSessionType: this.sessionType,
|
||||
name: this.name,
|
||||
type: this.type
|
||||
};
|
||||
}
|
||||
|
||||
processPdu(session: any, pdu: any, entity?: SmppSession | undefined): any {
|
||||
if (this.pduDoesApply(pdu)) {
|
||||
return this.doProcess(session, pdu, entity);
|
||||
}
|
||||
}
|
||||
protected pduDoesApply(pdu: any): boolean {
|
||||
if (pdu.command) {
|
||||
return this.applicableCommands.includes(pdu.command);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
serialize(): object {
|
||||
return {
|
||||
servesSessionType: this.sessionType,
|
||||
name: this.name,
|
||||
type: this.type
|
||||
};
|
||||
}
|
||||
protected abstract doProcess(session: any, pdu: any, entity?: SmppSession | undefined): any;
|
||||
}
|
||||
|
@@ -4,42 +4,42 @@ import Postprocessor from "../Postprocessor";
|
||||
const smpp = require("smpp");
|
||||
|
||||
export default class BindTranscieverReplyProcessor extends Postprocessor {
|
||||
applicableCommands: string[] = ['bind_transceiver'];
|
||||
applicableCommands: string[] = ['bind_transceiver'];
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
doProcess(session: any, pdu: any, entity?: Center | undefined): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!entity) {
|
||||
reject();
|
||||
}
|
||||
doProcess(session: any, pdu: any, entity?: Center | undefined): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!entity) {
|
||||
reject();
|
||||
}
|
||||
|
||||
this.logger.log1(`Center-${entity?.id} got a bind_transceiver with system_id ${pdu.system_id} and password ${pdu.password}`);
|
||||
session.pause();
|
||||
if (pdu.system_id === entity?.username && pdu.password === entity?.password) {
|
||||
this.logger.log1(`Center-${entity?.id} client connection successful`);
|
||||
if (pdu.response) {
|
||||
entity?.doSendPdu(pdu.response(), session);
|
||||
}
|
||||
session.resume();
|
||||
// @ts-ignore
|
||||
entity?.pendingSessions = entity?.pendingSessions.filter((s) => s !== session);
|
||||
entity?.sessions.push(session);
|
||||
entity?.updateStatus();
|
||||
} else {
|
||||
this.logger.log1(`Center-${entity?.id} client connection failed, invalid credentials (expected: ${entity?.username}, ${entity?.password})`);
|
||||
if (pdu.response) {
|
||||
entity?.doSendPdu(pdu.response({
|
||||
command_status: smpp.ESME_RBINDFAIL
|
||||
}), session);
|
||||
}
|
||||
// @ts-ignore
|
||||
entity?.pendingSessions = entity?.pendingSessions.filter((s) => s !== session);
|
||||
entity?.updateStatus();
|
||||
session.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
this.logger.log1(`Center-${entity?.id} got a bind_transceiver with system_id ${pdu.system_id} and password ${pdu.password}`);
|
||||
session.pause();
|
||||
if (pdu.system_id === entity?.username && pdu.password === entity?.password) {
|
||||
this.logger.log1(`Center-${entity?.id} client connection successful`);
|
||||
if (pdu.response) {
|
||||
entity?.doSendPdu(pdu.response(), session);
|
||||
}
|
||||
session.resume();
|
||||
// @ts-ignore
|
||||
entity.pendingSessions = entity?.pendingSessions.filter((s) => s !== session);
|
||||
entity?.sessions.push(session);
|
||||
entity?.updateStatus();
|
||||
} else {
|
||||
this.logger.log1(`Center-${entity?.id} client connection failed, invalid credentials (expected: ${entity?.username}, ${entity?.password})`);
|
||||
if (pdu.response) {
|
||||
entity?.doSendPdu(pdu.response({
|
||||
command_status: smpp.ESME_RBINDFAIL
|
||||
}), session);
|
||||
}
|
||||
// @ts-ignore
|
||||
entity.pendingSessions = entity?.pendingSessions.filter((s) => s !== session);
|
||||
entity?.updateStatus();
|
||||
session.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -6,38 +6,44 @@ const smpp = require("smpp");
|
||||
|
||||
export default class DeliveryReceiptProcessor extends Postprocessor {
|
||||
applicableCommands: string[] = ['submit_sm'];
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
if (pdu.registered_delivery) {
|
||||
let drMessage: string = "";
|
||||
let date: string = new Date().toISOString().replace(/T/, '').replace(/\..+/, '').replace(/-/g, '').replace(/:/g, '').substring(2, 12);
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
let relatedMessageId: number | undefined = MessageIdManager.getMessageId(pdu);
|
||||
if (relatedMessageId) {
|
||||
drMessage += "id:" + relatedMessageId + " ";
|
||||
drMessage += "sub:001 ";
|
||||
drMessage += "dlvrd:001 ";
|
||||
drMessage += "submit date:" + date + " ";
|
||||
drMessage += "done date:" + date + " ";
|
||||
drMessage += "stat:DELIVRD ";
|
||||
drMessage += "err:000 ";
|
||||
drMessage += "text:";
|
||||
sleep(ms: number) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
let DRPdu = new smpp.PDU('deliver_sm', {
|
||||
source_addr: pdu.source_addr,
|
||||
destination_addr: pdu.destination_addr,
|
||||
short_message: drMessage,
|
||||
esm_class: 4,
|
||||
});
|
||||
entity?.doSendPdu(DRPdu, session);
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
let drMessage: string = "";
|
||||
let date: string = new Date().toISOString().replace(/T/, '').replace(/\..+/, '').replace(/-/g, '').replace(/:/g, '').substring(2, 12);
|
||||
|
||||
resolve(pdu);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
let relatedMessageId: number | undefined = MessageIdManager.getMessageId(pdu);
|
||||
if (relatedMessageId) {
|
||||
drMessage += "id:" + relatedMessageId + " ";
|
||||
drMessage += "sub:001 ";
|
||||
drMessage += "dlvrd:001 ";
|
||||
drMessage += "submit date:" + date + " ";
|
||||
drMessage += "done date:" + date + " ";
|
||||
drMessage += "stat:DELIVRD ";
|
||||
drMessage += "err:000 ";
|
||||
drMessage += "text:";
|
||||
|
||||
let sleepTime = 0;
|
||||
let DRPdu = new smpp.PDU('deliver_sm', {
|
||||
source_addr: pdu.source_addr,
|
||||
destination_addr: pdu.destination_addr,
|
||||
short_message: drMessage,
|
||||
esm_class: 4,
|
||||
});
|
||||
setTimeout(() => entity?.doSendPdu(DRPdu, session), sleepTime);
|
||||
|
||||
resolve(pdu);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -5,20 +5,21 @@ const smpp = require("smpp");
|
||||
|
||||
export default class EchoPduProcessor extends Postprocessor {
|
||||
applicableCommands: string[] = ['submit_sm'];
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
// Temporary (?) safeguard against echoing long sms
|
||||
if (!pdu.short_message.udh) {
|
||||
let echoPdu = new smpp.PDU('deliver_sm', {...pdu});
|
||||
echoPdu.source_addr = pdu.destination_addr;
|
||||
echoPdu.destination_addr = pdu.source_addr;
|
||||
entity?.doSendPdu(echoPdu, session);
|
||||
resolve(echoPdu);
|
||||
}
|
||||
});
|
||||
}
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
// Temporary (?) safeguard against echoing long sms
|
||||
if (!pdu.short_message.udh) {
|
||||
let echoPdu = new smpp.PDU('deliver_sm', {...pdu});
|
||||
echoPdu.source_addr = pdu.destination_addr;
|
||||
echoPdu.destination_addr = pdu.source_addr;
|
||||
entity?.doSendPdu(echoPdu, session);
|
||||
resolve(echoPdu);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -2,16 +2,16 @@ import SmppSession from "../../../SmppSession";
|
||||
import Postprocessor from "../Postprocessor";
|
||||
|
||||
export default class EnquireLinkReplyProcessor extends Postprocessor {
|
||||
applicableCommands: string[] = ['enquire_link'];
|
||||
applicableCommands: string[] = ['enquire_link'];
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
entity?.doSendPdu(pdu.response(), session);
|
||||
resolve(pdu);
|
||||
});
|
||||
}
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
entity?.doSendPdu(pdu.response(), session);
|
||||
resolve(pdu);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -3,20 +3,20 @@ import SmppSession from "../../../SmppSession";
|
||||
import Postprocessor from "../Postprocessor";
|
||||
|
||||
export default class SubmitSmReplyProcessor extends Postprocessor {
|
||||
applicableCommands: string[] = ['submit_sm'];
|
||||
private messageIdIterator: number = 0;
|
||||
applicableCommands: string[] = ['submit_sm'];
|
||||
private messageIdIterator: number = 0;
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let response = pdu.response();
|
||||
response.message_id = this.messageIdIterator++;
|
||||
MessageIdManager.addMessageId(pdu, response.message_id);
|
||||
entity?.doSendPdu(response, session);
|
||||
resolve(pdu);
|
||||
});
|
||||
}
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let response = pdu.response();
|
||||
response.message_id = this.messageIdIterator++;
|
||||
MessageIdManager.addMessageId(pdu, response.message_id);
|
||||
entity?.doSendPdu(response, session);
|
||||
resolve(pdu);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -2,16 +2,16 @@ import SmppSession from "../../../SmppSession";
|
||||
import Postprocessor from "../Postprocessor";
|
||||
|
||||
export default class DeliverSmReplyProcessor extends Postprocessor {
|
||||
applicableCommands: string[] = ['deliver_sm'];
|
||||
applicableCommands: string[] = ['deliver_sm'];
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
entity?.doSendPdu(pdu.response(), session);
|
||||
resolve(pdu);
|
||||
});
|
||||
}
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
entity?.doSendPdu(pdu.response(), session);
|
||||
resolve(pdu);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import PduProcessor from "../PduProcessor";
|
||||
|
||||
export default abstract class Postprocessor extends PduProcessor {
|
||||
readonly type: string = Postprocessor.name;
|
||||
readonly type: string = Postprocessor.name;
|
||||
}
|
@@ -2,15 +2,15 @@ import SmppSession from "../../../SmppSession";
|
||||
import Preprocessor from "../Preprocessor";
|
||||
|
||||
export default class DeliveryReceiptRequestProcessor extends Preprocessor {
|
||||
applicableCommands: string[] = ['submit_sm'];
|
||||
applicableCommands: string[] = ['submit_sm'];
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
pdu.registered_delivery = 1;
|
||||
});
|
||||
}
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
pdu.registered_delivery = 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -3,21 +3,21 @@ import Preprocessor from "../Preprocessor";
|
||||
|
||||
export default class DestinationEnumeratorProcessor extends Preprocessor {
|
||||
applicableCommands: string[] = ['submit_sm', 'deliver_sm'];
|
||||
private iterator: number = 0;
|
||||
private iterator: number = 0;
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
if (!!pdu.destination_addr) {
|
||||
pdu.destination_addr = pdu.destination_addr + this.padLeft(String(this.iterator++), '0', 5);
|
||||
}
|
||||
});
|
||||
}
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
if (!!pdu.destination_addr) {
|
||||
pdu.destination_addr = pdu.destination_addr + this.padLeft(String(this.iterator++), '0', 5);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private padLeft(str: string, pad: string, length: number): string {
|
||||
return (new Array(length + 1).join(pad) + str).slice(-length);
|
||||
}
|
||||
private padLeft(str: string, pad: string, length: number): string {
|
||||
return (new Array(length + 1).join(pad) + str).slice(-length);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,40 @@
|
||||
import {PDU} from "../../../CommonObjects";
|
||||
import SmppSession from "../../../SmppSession";
|
||||
import Preprocessor from "../Preprocessor";
|
||||
|
||||
export default class DestinationSetPreprocessor extends Preprocessor {
|
||||
applicableCommands: string[] = ['submit_sm', 'deliver_sm'];
|
||||
private sourceSet: string[] = [];
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
while (this.sourceSet.length < 100) {
|
||||
this.sourceSet.push(this.getRandomInt(100000, 999999).toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: PDU, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
if (pdu.short_message) {
|
||||
if (pdu.short_message.includes("arg:")) {
|
||||
let temp: string = pdu.short_message.split(";");
|
||||
let arg: number = Number(temp[0].split(":")[1]);
|
||||
while (this.sourceSet.length < arg) {
|
||||
this.sourceSet.push(this.getRandomInt(100000, 999999).toString());
|
||||
}
|
||||
while (this.sourceSet.length > arg) {
|
||||
this.sourceSet.pop();
|
||||
}
|
||||
pdu.short_message = temp[1];
|
||||
}
|
||||
}
|
||||
pdu.destination_addr = pdu.destination_addr + this.sourceSet[this.getRandomInt(0, this.sourceSet.length)];
|
||||
});
|
||||
}
|
||||
|
||||
private getRandomInt(min: number, max: number): number {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
return Math.floor(Math.random() * (max - min) + min);
|
||||
}
|
||||
}
|
17
src/PDUProcessor/Preprocessor/Client/GSM0338Preprocessor.ts
Normal file
17
src/PDUProcessor/Preprocessor/Client/GSM0338Preprocessor.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import {PDU} from "../../../CommonObjects";
|
||||
import SmppSession from "../../../SmppSession";
|
||||
import Preprocessor from "../Preprocessor";
|
||||
|
||||
export default class GSM0338Preprocessor extends Preprocessor {
|
||||
applicableCommands: string[] = ['submit_sm', 'deliver_sm'];
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: PDU, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
pdu.data_coding = 0xf6;
|
||||
});
|
||||
}
|
||||
}
|
@@ -5,83 +5,83 @@ import Preprocessor from "../Preprocessor";
|
||||
const smpp = require('smpp');
|
||||
|
||||
export default class LongSmsProcessor extends Preprocessor {
|
||||
static readonly maxMessageSizeBits = 1072;
|
||||
applicableCommands: string[] = ['submit_sm', 'deliver_sm'];
|
||||
static readonly maxMessageSizeBits = 1072;
|
||||
private iterator: number = 0;
|
||||
private iterator: number = 0;
|
||||
|
||||
constructor(type: string) {
|
||||
// An sms can have a maximum length (short_message) of 1120 bits or 140 bytes.
|
||||
// For a message encoded in UCS-2, the maximum length is 70 characters. (2 bytes per character)
|
||||
// For a message encoded in GSM-7, the maximum length is 160 characters. (7 bits per character)
|
||||
// Once a message is split the part information is placed into udh
|
||||
// Like
|
||||
// destination_addr: config.destinationAddress,
|
||||
// short_message: {
|
||||
// udh: Buffer.from([0x05, 0x00, 0x03, 0x05, 0x02, 0x01]),
|
||||
// message: "Hello World!"
|
||||
// }
|
||||
// The UDH parameters are as follows:
|
||||
// 0x05: Length of UDH (5 bytes to follow)
|
||||
// 0x00: Concatenated message Information Element (8-bit reference number)
|
||||
// 0x03: Length of Information Element data (3 bytes to follow)
|
||||
// 0xXX: Reference number for this concatenated message
|
||||
// 0xYY: Number of fragments in the concatenated message
|
||||
// 0xZZ: Fragment number/index within the concatenated message 1072
|
||||
super(type);
|
||||
}
|
||||
constructor(type: string) {
|
||||
// An sms can have a maximum length (short_message) of 1120 bits or 140 bytes.
|
||||
// For a message encoded in UCS-2, the maximum length is 70 characters. (2 bytes per character)
|
||||
// For a message encoded in GSM-7, the maximum length is 160 characters. (7 bits per character)
|
||||
// Once a message is split the part information is placed into udh
|
||||
// Like
|
||||
// destination_addr: config.destinationAddress,
|
||||
// short_message: {
|
||||
// udh: Buffer.from([0x05, 0x00, 0x03, 0x05, 0x02, 0x01]),
|
||||
// message: "Hello World!"
|
||||
// }
|
||||
// The UDH parameters are as follows:
|
||||
// 0x05: Length of UDH (5 bytes to follow)
|
||||
// 0x00: Concatenated message Information Element (8-bit reference number)
|
||||
// 0x03: Length of Information Element data (3 bytes to follow)
|
||||
// 0xXX: Reference number for this concatenated message
|
||||
// 0xYY: Number of fragments in the concatenated message
|
||||
// 0xZZ: Fragment number/index within the concatenated message 1072
|
||||
super(type);
|
||||
}
|
||||
|
||||
static getCharacterSizeForEncoding(pdu: PDU) {
|
||||
let encoding: number | undefined = pdu.data_coding;
|
||||
if (!encoding) {
|
||||
encoding = 0;
|
||||
}
|
||||
let characterSizeBits: number = 0;
|
||||
switch (encoding) {
|
||||
case 0:
|
||||
case 1:
|
||||
characterSizeBits = 8;
|
||||
break;
|
||||
case 8:
|
||||
characterSizeBits = 16;
|
||||
break;
|
||||
}
|
||||
return characterSizeBits;
|
||||
}
|
||||
static getCharacterSizeForEncoding(pdu: PDU) {
|
||||
let encoding: number | undefined = pdu.data_coding;
|
||||
if (!encoding) {
|
||||
encoding = 0;
|
||||
}
|
||||
let characterSizeBits: number = 0;
|
||||
switch (encoding) {
|
||||
case 0:
|
||||
case 1:
|
||||
characterSizeBits = 8;
|
||||
break;
|
||||
case 8:
|
||||
characterSizeBits = 16;
|
||||
break;
|
||||
}
|
||||
return characterSizeBits;
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: PDU, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
if (!!pdu.short_message) {
|
||||
let characterSizeBits: number = LongSmsProcessor.getCharacterSizeForEncoding(pdu);
|
||||
let maxMessageLength: number = LongSmsProcessor.maxMessageSizeBits / characterSizeBits;
|
||||
if (characterSizeBits) {
|
||||
let splitMessage: string[] = [];
|
||||
let message: string = pdu.short_message;
|
||||
let messageLength: number = message.length;
|
||||
let messageCount: number = Math.ceil(messageLength / maxMessageLength);
|
||||
for (let i = 0; i < messageCount; i++) {
|
||||
splitMessage.push(message.substr(i * maxMessageLength, maxMessageLength));
|
||||
}
|
||||
protected doProcess(session: any, pdu: PDU, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
if (!!pdu.short_message) {
|
||||
let characterSizeBits: number = LongSmsProcessor.getCharacterSizeForEncoding(pdu);
|
||||
let maxMessageLength: number = LongSmsProcessor.maxMessageSizeBits / characterSizeBits;
|
||||
if (characterSizeBits) {
|
||||
let splitMessage: string[] = [];
|
||||
let message: string = pdu.short_message;
|
||||
let messageLength: number = message.length;
|
||||
let messageCount: number = Math.ceil(messageLength / maxMessageLength);
|
||||
for (let i = 0; i < messageCount; i++) {
|
||||
splitMessage.push(message.substr(i * maxMessageLength, maxMessageLength));
|
||||
}
|
||||
|
||||
splitMessage.forEach((messagePart: string, index: number) => {
|
||||
let udh: Buffer = Buffer.from([0x05, 0x00, 0x03, this.iterator++, messageCount, index + 1]);
|
||||
splitMessage.forEach((messagePart: string, index: number) => {
|
||||
let udh: Buffer = Buffer.from([0x05, 0x00, 0x03, this.iterator++, messageCount, index + 1]);
|
||||
|
||||
if (index < (messageCount - 1)) {
|
||||
let partPdu = new smpp.PDU(pdu.command, {...pdu});
|
||||
partPdu.short_message = {
|
||||
udh: udh,
|
||||
message: messagePart
|
||||
}
|
||||
entity?.doSendPdu(partPdu, session);
|
||||
} else {
|
||||
pdu.short_message = {
|
||||
udh: udh,
|
||||
message: messagePart
|
||||
}
|
||||
resolve(pdu);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (index < (messageCount - 1)) {
|
||||
let partPdu = new smpp.PDU(pdu.command, {...pdu});
|
||||
partPdu.short_message = {
|
||||
udh: udh,
|
||||
message: messagePart
|
||||
}
|
||||
entity?.doSendPdu(partPdu, session);
|
||||
} else {
|
||||
pdu.short_message = {
|
||||
udh: udh,
|
||||
message: messagePart
|
||||
}
|
||||
resolve(pdu);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,16 @@
|
||||
import SmppSession from "../../../SmppSession";
|
||||
import Preprocessor from "../Preprocessor";
|
||||
|
||||
export default class ProtocolId2DigitProcessor extends Preprocessor {
|
||||
applicableCommands: string[] = ['submit_sm', 'deliver_sm'];
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
pdu.protocol_id = 16;
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
import SmppSession from "../../../SmppSession";
|
||||
import Preprocessor from "../Preprocessor";
|
||||
|
||||
export default class ProtocolId3DigitProcessor extends Preprocessor {
|
||||
applicableCommands: string[] = ['submit_sm', 'deliver_sm'];
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
pdu.protocol_id = 128;
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
import {PDU} from "../../../CommonObjects";
|
||||
import SmppSession from "../../../SmppSession";
|
||||
import Preprocessor from "../Preprocessor";
|
||||
|
||||
export default class ProtocolId4DigitProcessor extends Preprocessor {
|
||||
applicableCommands: string[] = ['submit_sm', 'deliver_sm'];
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: PDU, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
pdu.data_coding = 2048;
|
||||
});
|
||||
}
|
||||
}
|
16
src/PDUProcessor/Preprocessor/Client/ProtocolIdProcessor.ts
Normal file
16
src/PDUProcessor/Preprocessor/Client/ProtocolIdProcessor.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import SmppSession from "../../../SmppSession";
|
||||
import Preprocessor from "../Preprocessor";
|
||||
|
||||
export default class ProtocolIdProcessor extends Preprocessor {
|
||||
applicableCommands: string[] = ['submit_sm', 'deliver_sm'];
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
pdu.protocol_id = 1;
|
||||
});
|
||||
}
|
||||
}
|
@@ -2,22 +2,22 @@ import SmppSession from "../../../SmppSession";
|
||||
import Preprocessor from "../Preprocessor";
|
||||
|
||||
export default class SourceEnumeratorProcessor extends Preprocessor {
|
||||
applicableCommands: string[] = ['submit_sm', 'deliver_sm'];
|
||||
private iterator: number = 0;
|
||||
applicableCommands: string[] = ['submit_sm', 'deliver_sm'];
|
||||
private iterator: number = 0;
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
if (!!pdu.source_addr) {
|
||||
pdu.source_addr = pdu.source_addr + this.padLeft(String(this.iterator++), '0', 5);
|
||||
}
|
||||
});
|
||||
}
|
||||
protected doProcess(session: any, pdu: any, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
if (!!pdu.source_addr) {
|
||||
pdu.source_addr = pdu.source_addr + this.padLeft(String(this.iterator++), '0', 5);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private padLeft(str: string, pad: string, length: number): string {
|
||||
return (new Array(length + 1).join(pad) + str).slice(-length);
|
||||
}
|
||||
private padLeft(str: string, pad: string, length: number): string {
|
||||
return (new Array(length + 1).join(pad) + str).slice(-length);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,40 @@
|
||||
import {PDU} from "../../../CommonObjects";
|
||||
import SmppSession from "../../../SmppSession";
|
||||
import Preprocessor from "../Preprocessor";
|
||||
|
||||
export default class SourceSetPreprocessor extends Preprocessor {
|
||||
applicableCommands: string[] = ['submit_sm', 'deliver_sm'];
|
||||
private sourceSet: string[] = [];
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
while (this.sourceSet.length < 100) {
|
||||
this.sourceSet.push(this.getRandomInt(100000, 999999).toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: PDU, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
if (pdu.short_message) {
|
||||
if (pdu.short_message.includes("arg:")) {
|
||||
let temp: string = pdu.short_message.split(";");
|
||||
let arg: number = Number(temp[0].split(":")[1]);
|
||||
while (this.sourceSet.length < arg) {
|
||||
this.sourceSet.push(this.getRandomInt(100000, 999999).toString());
|
||||
}
|
||||
while (this.sourceSet.length > arg) {
|
||||
this.sourceSet.pop();
|
||||
}
|
||||
pdu.short_message = temp[1];
|
||||
}
|
||||
}
|
||||
pdu.source_addr = pdu.source_addr + this.sourceSet[this.getRandomInt(0, this.sourceSet.length)];
|
||||
});
|
||||
}
|
||||
|
||||
private getRandomInt(min: number, max: number): number {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
return Math.floor(Math.random() * (max - min) + min);
|
||||
}
|
||||
}
|
17
src/PDUProcessor/Preprocessor/Client/UCS2Preprocessor.ts
Normal file
17
src/PDUProcessor/Preprocessor/Client/UCS2Preprocessor.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import {PDU} from "../../../CommonObjects";
|
||||
import SmppSession from "../../../SmppSession";
|
||||
import Preprocessor from "../Preprocessor";
|
||||
|
||||
export default class UCS2Preprocessor extends Preprocessor {
|
||||
applicableCommands: string[] = ['submit_sm', 'deliver_sm'];
|
||||
|
||||
constructor(type: string) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
protected doProcess(session: any, pdu: PDU, entity?: SmppSession | undefined): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
pdu.data_coding = 8;
|
||||
});
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
import PduProcessor from "../PduProcessor";
|
||||
|
||||
export default abstract class Preprocessor extends PduProcessor {
|
||||
readonly type: string = Preprocessor.name;
|
||||
readonly type: string = Preprocessor.name;
|
||||
}
|
@@ -12,98 +12,120 @@ import DeliverSmReplyProcessor from "./Postprocessor/Client/DeliverSmReplyProces
|
||||
import Postprocessor from "./Postprocessor/Postprocessor";
|
||||
import DeliveryReceiptRequestProcessor from "./Preprocessor/Client/DeliveryReceiptRequestProcessor";
|
||||
import DestinationEnumeratorProcessor from "./Preprocessor/Client/DestinationEnumeratorProcessor";
|
||||
import DestinationSetPreprocessor from "./Preprocessor/Client/DestinationSetPreprocessor";
|
||||
import GSM0338Preprocessor from "./Preprocessor/Client/GSM0338Preprocessor";
|
||||
import LongSmsProcessor from "./Preprocessor/Client/LongSmsProcessor";
|
||||
import ProtocolId2DigitProcessor from "./Preprocessor/Client/ProtocolId-2Digit-Processor";
|
||||
import ProtocolId3DigitProcessor from "./Preprocessor/Client/ProtocolId-3Digit-Processor";
|
||||
import ProtocolIdProcessor from "./Preprocessor/Client/ProtocolIdProcessor";
|
||||
import SourceEnumeratorProcessor from "./Preprocessor/Client/SourceEnumeratorProcessor";
|
||||
import SourceSetPreprocessor from "./Preprocessor/Client/SourceSetPreprocessor";
|
||||
import UCS2Preprocessor from "./Preprocessor/Client/UCS2Preprocessor";
|
||||
import Preprocessor from "./Preprocessor/Preprocessor";
|
||||
|
||||
export default class ProcessorManager {
|
||||
static preprocessors: PduProcessor[];
|
||||
static postprocessors: PduProcessor[];
|
||||
private static readonly logger: Logger = new Logger(this.name);
|
||||
static preprocessors: PduProcessor[];
|
||||
static postprocessors: PduProcessor[];
|
||||
private static readonly logger: Logger = new Logger(this.name);
|
||||
|
||||
constructor() {
|
||||
// This is an IDIOTIC solution, but it works
|
||||
// Try running eb22a43 to find out what's wrong with the previous approach
|
||||
ProcessorManager.postprocessors = [
|
||||
new EnquireLinkReplyProcessor(Center.name),
|
||||
new DeliverSmReplyProcessor(Client.name),
|
||||
new SubmitSmReplyProcessor(Center.name),
|
||||
new BindTranscieverReplyProcessor(Center.name),
|
||||
new EchoPduProcessor(Center.name),
|
||||
new DeliveryReceiptProcessor(Center.name)
|
||||
];
|
||||
ProcessorManager.preprocessors = [
|
||||
new DestinationEnumeratorProcessor(Client.name),
|
||||
new SourceEnumeratorProcessor(Client.name),
|
||||
new DestinationEnumeratorProcessor(Center.name),
|
||||
new SourceEnumeratorProcessor(Center.name),
|
||||
new DeliveryReceiptRequestProcessor(Client.name),
|
||||
new LongSmsProcessor(Client.name)
|
||||
];
|
||||
}
|
||||
constructor() {
|
||||
// This is an IDIOTIC solution, but it works
|
||||
// Try running eb22a43 to find out what's wrong with the previous approach
|
||||
ProcessorManager.postprocessors = [
|
||||
new EnquireLinkReplyProcessor(Center.name),
|
||||
new DeliverSmReplyProcessor(Client.name),
|
||||
new SubmitSmReplyProcessor(Center.name),
|
||||
new BindTranscieverReplyProcessor(Center.name),
|
||||
new EchoPduProcessor(Center.name),
|
||||
new DeliveryReceiptProcessor(Center.name)
|
||||
];
|
||||
ProcessorManager.preprocessors = [
|
||||
new DestinationEnumeratorProcessor(Client.name),
|
||||
new SourceEnumeratorProcessor(Client.name),
|
||||
new DestinationEnumeratorProcessor(Center.name),
|
||||
new SourceEnumeratorProcessor(Center.name),
|
||||
new DeliveryReceiptRequestProcessor(Client.name),
|
||||
new LongSmsProcessor(Client.name),
|
||||
new LongSmsProcessor(Center.name),
|
||||
new ProtocolIdProcessor(Client.name),
|
||||
new ProtocolIdProcessor(Center.name),
|
||||
new UCS2Preprocessor(Client.name),
|
||||
new UCS2Preprocessor(Center.name),
|
||||
new ProtocolId2DigitProcessor(Client.name),
|
||||
new ProtocolId2DigitProcessor(Center.name),
|
||||
new ProtocolId3DigitProcessor(Client.name),
|
||||
new ProtocolId3DigitProcessor(Center.name),
|
||||
new SourceSetPreprocessor(Client.name),
|
||||
new SourceSetPreprocessor(Center.name),
|
||||
new DestinationSetPreprocessor(Client.name),
|
||||
new DestinationSetPreprocessor(Center.name),
|
||||
new GSM0338Preprocessor(Client.name),
|
||||
new GSM0338Preprocessor(Center.name)
|
||||
];
|
||||
}
|
||||
|
||||
static get processors(): PduProcessor[] {
|
||||
return this.preprocessors.concat(this.postprocessors);
|
||||
}
|
||||
static get processors(): PduProcessor[] {
|
||||
return this.preprocessors.concat(this.postprocessors);
|
||||
}
|
||||
|
||||
static getProcessors(name: string): PduProcessor[] {
|
||||
this.logger.log1(`Looking for processor with name ${name}...`);
|
||||
let pduProcessors: PduProcessor[] = this.processors.filter((processor: PduProcessor) => processor.name === name);
|
||||
this.logger.log1(`Found ${pduProcessors.length} processor(s) with name ${name}`);
|
||||
return pduProcessors;
|
||||
}
|
||||
static getProcessors(name: string): PduProcessor[] {
|
||||
this.logger.log1(`Looking for processor with name ${name}...`);
|
||||
let pduProcessors: PduProcessor[] = this.processors.filter((processor: PduProcessor) => processor.name === name);
|
||||
this.logger.log1(`Found ${pduProcessors.length} processor(s) with name ${name}`);
|
||||
return pduProcessors;
|
||||
}
|
||||
|
||||
static attachProcessors(session: SmppSession, processors: PduProcessor[]): void {
|
||||
this.logger.log1(`Trying to attach processor ${processors.toString()} to session ${session.constructor.name}-${session.id}`);
|
||||
for (const processor of processors) {
|
||||
if (this.areCompatible(session, processor)) {
|
||||
// This could be done a little better but this is OK for now
|
||||
switch (processor.type) {
|
||||
case Preprocessor.name:
|
||||
session.attachPreprocessor(processor);
|
||||
break;
|
||||
case Postprocessor.name:
|
||||
session.attachPostprocessor(processor);
|
||||
break;
|
||||
default:
|
||||
this.logger.log1(`Processor ${processor.name} is not a preprocessor or a postprocessor`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static attachProcessors(session: SmppSession, processors: PduProcessor[]): void {
|
||||
this.logger.log1(`Trying to attach processor ${processors.toString()} to session ${session.constructor.name}-${session.id}`);
|
||||
for (const processor of processors) {
|
||||
if (this.areCompatible(session, processor)) {
|
||||
// This could be done a little better but this is OK for now
|
||||
switch (processor.type) {
|
||||
case Preprocessor.name:
|
||||
session.attachPreprocessor(processor);
|
||||
break;
|
||||
case Postprocessor.name:
|
||||
session.attachPostprocessor(processor);
|
||||
break;
|
||||
default:
|
||||
this.logger.log1(`Processor ${processor.name} is not a preprocessor or a postprocessor`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static detachProcessors(session: SmppSession, processors: PduProcessor[]): void {
|
||||
this.logger.log1(`Trying to detach processors ${processors.toString()} from session ${session.constructor.name}-${session.id}`);
|
||||
for (const processor of processors) {
|
||||
switch (processor.type) {
|
||||
case Preprocessor.name:
|
||||
session.detachPreprocessor(processor);
|
||||
break;
|
||||
case Postprocessor.name:
|
||||
session.detachPostprocessor(processor);
|
||||
break;
|
||||
default:
|
||||
this.logger.log1(`Processor ${processor.name} is not a preprocessor or a postprocessor`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static detachProcessors(session: SmppSession, processors: PduProcessor[]): void {
|
||||
this.logger.log1(`Trying to detach processors ${processors.toString()} from session ${session.constructor.name}-${session.id}`);
|
||||
for (const processor of processors) {
|
||||
switch (processor.type) {
|
||||
case Preprocessor.name:
|
||||
session.detachPreprocessor(processor);
|
||||
break;
|
||||
case Postprocessor.name:
|
||||
session.detachPostprocessor(processor);
|
||||
break;
|
||||
default:
|
||||
this.logger.log1(`Processor ${processor.name} is not a preprocessor or a postprocessor`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static areCompatible(session: SmppSession, processor: PduProcessor): boolean {
|
||||
this.logger.log1(`Checking compatibility between session ${session.constructor.name}-${session.id} and processor ${processor.name}`);
|
||||
return session.constructor.name === processor.sessionType;
|
||||
}
|
||||
static areCompatible(session: SmppSession, processor: PduProcessor): boolean {
|
||||
this.logger.log1(`Checking compatibility between session ${session.constructor.name}-${session.id} and processor ${processor.name}`);
|
||||
return session.constructor.name === processor.sessionType;
|
||||
}
|
||||
|
||||
static getProcessorsForType(type: string): PduProcessor[] {
|
||||
return this.processors.filter((processor: PduProcessor) => processor.sessionType === type);
|
||||
}
|
||||
static getProcessorsForType(type: string): PduProcessor[] {
|
||||
return this.processors.filter((processor: PduProcessor) => processor.sessionType === type);
|
||||
}
|
||||
|
||||
static getPreprocessorsForType(type: string): PduProcessor[] {
|
||||
return this.preprocessors.filter((processor: PduProcessor) => processor.sessionType === type);
|
||||
}
|
||||
static getPreprocessorsForType(type: string): PduProcessor[] {
|
||||
return this.preprocessors.filter((processor: PduProcessor) => processor.sessionType === type);
|
||||
}
|
||||
|
||||
static getPostprocessorsForType(type: string): PduProcessor[] {
|
||||
return this.postprocessors.filter((processor: PduProcessor) => processor.sessionType === type);
|
||||
}
|
||||
static getPostprocessorsForType(type: string): PduProcessor[] {
|
||||
return this.postprocessors.filter((processor: PduProcessor) => processor.sessionType === type);
|
||||
}
|
||||
}
|
||||
|
@@ -1,29 +1,29 @@
|
||||
export default class PersistentPromise {
|
||||
private readonly promise: Promise<any>;
|
||||
private promiseResolve: ((value?: any) => void) | undefined;
|
||||
private promiseReject: ((reason?: any) => void) | undefined;
|
||||
private readonly promise: Promise<any>;
|
||||
private promiseResolve: ((value?: any) => void) | undefined;
|
||||
private promiseReject: ((reason?: any) => void) | undefined;
|
||||
|
||||
constructor(callback: (resolve: (value?: any) => void, reject: (reason?: any) => void) => void) {
|
||||
this.promise = new Promise((resolve, reject) => {
|
||||
this.promiseResolve = resolve;
|
||||
this.promiseReject = reject;
|
||||
callback(resolve, reject);
|
||||
});
|
||||
}
|
||||
constructor(callback: (resolve: (value?: any) => void, reject: (reason?: any) => void) => void) {
|
||||
this.promise = new Promise((resolve, reject) => {
|
||||
this.promiseResolve = resolve;
|
||||
this.promiseReject = reject;
|
||||
callback(resolve, reject);
|
||||
});
|
||||
}
|
||||
|
||||
resolve(value?: any): void {
|
||||
if (this.promiseResolve) {
|
||||
this.promiseResolve(value);
|
||||
}
|
||||
}
|
||||
resolve(value?: any): void {
|
||||
if (this.promiseResolve) {
|
||||
this.promiseResolve(value);
|
||||
}
|
||||
}
|
||||
|
||||
reject(reason?: any): void {
|
||||
if (this.promiseReject) {
|
||||
this.promiseReject(reason);
|
||||
}
|
||||
}
|
||||
reject(reason?: any): void {
|
||||
if (this.promiseReject) {
|
||||
this.promiseReject(reason);
|
||||
}
|
||||
}
|
||||
|
||||
then(onfulfilled?: ((value: any) => any) | undefined | null, onrejected?: ((reason: any) => any) | undefined | null): Promise<any> {
|
||||
return this.promise.then(onfulfilled, onrejected);
|
||||
}
|
||||
then(onfulfilled?: ((value: any) => any) | undefined | null, onrejected?: ((reason: any) => any) | undefined | null): Promise<any> {
|
||||
return this.promise.then(onfulfilled, onrejected);
|
||||
}
|
||||
}
|
@@ -7,138 +7,138 @@ import ProcessorManager from "./PDUProcessor/ProcessorManager";
|
||||
import SmppSession from "./SmppSession";
|
||||
|
||||
export default abstract class SessionManager {
|
||||
// I could've done this by passing these abstract properties to the constructor, but I wanted to have the possibility
|
||||
// of implementing additional methods
|
||||
abstract comparatorFn: (arg: any, session: SmppSession) => boolean;
|
||||
readonly abstract identifier: string;
|
||||
readonly abstract ManagedSessionClass: any;
|
||||
readonly abstract StorageFile: string;
|
||||
readonly SESSION_ADDED_EVENT: string = "SESSION ADDED";
|
||||
// I could've done this by passing these abstract properties to the constructor, but I wanted to have the possibility
|
||||
// of implementing additional methods
|
||||
abstract comparatorFn: (arg: any, session: SmppSession) => boolean;
|
||||
readonly abstract identifier: string;
|
||||
readonly abstract ManagedSessionClass: any;
|
||||
readonly abstract StorageFile: string;
|
||||
readonly SESSION_ADDED_EVENT: string = "SESSION ADDED";
|
||||
|
||||
sessions: SmppSession[] = [];
|
||||
sessionId: number = 0;
|
||||
readonly logger: Logger = new Logger("SessionManager");
|
||||
readonly eventEmitter: EventEmitter = new EventEmitter();
|
||||
sessions: SmppSession[] = [];
|
||||
sessionId: number = 0;
|
||||
readonly logger: Logger = new Logger("SessionManager");
|
||||
readonly eventEmitter: EventEmitter = new EventEmitter();
|
||||
|
||||
addSession(session: SmppSession): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
this.logger.log1(`Adding session with id ${session.id}`);
|
||||
this.sessions.push(session);
|
||||
this.eventEmitter.emit(this.SESSION_ADDED_EVENT, session.id);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
addSession(session: SmppSession): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
this.logger.log1(`Adding session with id ${session.id}`);
|
||||
this.sessions.push(session);
|
||||
this.eventEmitter.emit(this.SESSION_ADDED_EVENT, session.id);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
on(event: string, listener: (...args: any[]) => void): void {
|
||||
this.eventEmitter.on(event, listener);
|
||||
}
|
||||
on(event: string, listener: (...args: any[]) => void): void {
|
||||
this.eventEmitter.on(event, listener);
|
||||
}
|
||||
|
||||
getSessions(): Promise<SmppSession[]> {
|
||||
return Promise.resolve(this.sessions);
|
||||
}
|
||||
getSessions(): Promise<SmppSession[]> {
|
||||
return Promise.resolve(this.sessions);
|
||||
}
|
||||
|
||||
removeSession(session: SmppSession): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
this.logger.log1(`Removing session with id ${session.id}`);
|
||||
session.close();
|
||||
session.destroy();
|
||||
this.sessions = this.sessions.filter(s => s.id !== session.id);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
removeSession(session: SmppSession): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
this.logger.log1(`Removing session with id ${session.id}`);
|
||||
session.close();
|
||||
session.destroy();
|
||||
this.sessions = this.sessions.filter(s => s.id !== session.id);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
getSession(id: number): Promise<SmppSession> {
|
||||
return new Promise<SmppSession>((resolve, reject) => {
|
||||
this.logger.log1(`Looking for session with id ${id}...`);
|
||||
let session: SmppSession | undefined = this.sessions.find(s => s.id == 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`);
|
||||
}
|
||||
});
|
||||
}
|
||||
getSession(id: number): Promise<SmppSession> {
|
||||
return new Promise<SmppSession>((resolve, reject) => {
|
||||
this.logger.log1(`Looking for session with id ${id}...`);
|
||||
let session: SmppSession | undefined = this.sessions.find(s => s.id == 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`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setup(): void {
|
||||
try {
|
||||
this.logger.log1(`Loading ${this.ManagedSessionClass.name} from ${this.StorageFile}`)
|
||||
let sessions: Buffer = fs.readFileSync(this.StorageFile);
|
||||
let loadedSessions: any[] = JSON.parse(String(sessions));
|
||||
this.logger.log1(`Loaded ${loadedSessions.length} clients from ${this.StorageFile}`);
|
||||
loadedSessions.forEach(session => {
|
||||
this.createSession(session.url || session.port, session.username, session.password).then((sessionObj: SmppSession) => {
|
||||
sessionObj.defaultSingleJob = Job.deserialize(session.defaultSingleJob);
|
||||
sessionObj.defaultMultipleJob = Job.deserialize(session.defaultMultipleJob);
|
||||
setup(): void {
|
||||
try {
|
||||
this.logger.log1(`Loading ${this.ManagedSessionClass.name} from ${this.StorageFile}`)
|
||||
let sessions: Buffer = fs.readFileSync(this.StorageFile);
|
||||
let loadedSessions: any[] = JSON.parse(String(sessions));
|
||||
this.logger.log1(`Loaded ${loadedSessions.length} clients from ${this.StorageFile}`);
|
||||
loadedSessions.forEach(session => {
|
||||
this.createSession(session.url || session.port, session.username, session.password).then((sessionObj: SmppSession) => {
|
||||
sessionObj.defaultSingleJob = Job.deserialize(session.defaultSingleJob);
|
||||
sessionObj.defaultMultipleJob = Job.deserialize(session.defaultMultipleJob);
|
||||
|
||||
let loadedProcessors: PduProcessor[] = session.preprocessors.concat(session.postprocessors);
|
||||
sessionObj.appliedProcessors.forEach((processor: PduProcessor) => {
|
||||
let processorsToDetach: PduProcessor[] = loadedProcessors.filter(p => p.name === processor.name);
|
||||
ProcessorManager.detachProcessors(sessionObj, processorsToDetach);
|
||||
});
|
||||
loadedProcessors.forEach((processor: PduProcessor) => {
|
||||
if (!sessionObj.appliedProcessors.find(p => p.name === processor.name)) {
|
||||
ProcessorManager.attachProcessors(sessionObj, ProcessorManager.getProcessors(processor.name));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
this.logger.log1(`Error loading centers from ${this.StorageFile}: ${e}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
let loadedProcessors: PduProcessor[] = session.preprocessors.concat(session.postprocessors);
|
||||
sessionObj.appliedProcessors.forEach((processor: PduProcessor) => {
|
||||
let processorsToDetach: PduProcessor[] = loadedProcessors.filter(p => p.name === processor.name);
|
||||
ProcessorManager.detachProcessors(sessionObj, processorsToDetach);
|
||||
});
|
||||
loadedProcessors.forEach((processor: PduProcessor) => {
|
||||
if (!sessionObj.appliedProcessors.find(p => p.name === processor.name)) {
|
||||
ProcessorManager.attachProcessors(sessionObj, ProcessorManager.getProcessors(processor.name));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
this.logger.log1(`Error loading centers from ${this.StorageFile}: ${e}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
createSession(arg: any, username: string, password: string): Promise<SmppSession> {
|
||||
return new Promise<SmppSession>((resolve, reject) => {
|
||||
this.logger.log1(`Creating session of type ${this.ManagedSessionClass.name} with arg ${arg}`);
|
||||
this.getExisting(arg).then((s: SmppSession) => {
|
||||
resolve(s);
|
||||
}, err => {
|
||||
});
|
||||
this.verifyField(arg, reject);
|
||||
username = username || "";
|
||||
password = password || "";
|
||||
createSession(arg: any, username: string, password: string): Promise<SmppSession> {
|
||||
return new Promise<SmppSession>((resolve, reject) => {
|
||||
this.logger.log1(`Creating session of type ${this.ManagedSessionClass.name} with arg ${arg}`);
|
||||
this.getExisting(arg).then((s: SmppSession) => {
|
||||
resolve(s);
|
||||
}, err => {
|
||||
});
|
||||
this.verifyField(arg, reject);
|
||||
username = username || "";
|
||||
password = password || "";
|
||||
|
||||
let session = new this.ManagedSessionClass(this.sessionId++, arg, username, password);
|
||||
this.addSession(session).then(() => {
|
||||
resolve(session);
|
||||
});
|
||||
});
|
||||
}
|
||||
let session = new this.ManagedSessionClass(this.sessionId++, arg, username, password);
|
||||
this.addSession(session).then(() => {
|
||||
resolve(session);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
verifyField(field: string, reject: (reason?: any) => void) {
|
||||
if (!field) {
|
||||
let error = `Request to make a new session failed because of missing ${field}.`;
|
||||
this.logger.log1(error);
|
||||
reject(error);
|
||||
}
|
||||
}
|
||||
verifyField(field: string, reject: (reason?: any) => void) {
|
||||
if (!field) {
|
||||
let error = `Request to make a new session failed because of missing ${field}.`;
|
||||
this.logger.log1(error);
|
||||
reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
cleanup(): void {
|
||||
this.logger.log1(`Saving centers to ${this.StorageFile}...`);
|
||||
fs.writeFileSync(this.StorageFile, JSON.stringify(this.serialize(), null, 4));
|
||||
}
|
||||
cleanup(): void {
|
||||
this.logger.log1(`Saving centers to ${this.StorageFile}...`);
|
||||
fs.writeFileSync(this.StorageFile, JSON.stringify(this.serialize(), null, 4));
|
||||
}
|
||||
|
||||
serialize(): object {
|
||||
this.logger.log1(`Serializing ${this.sessions.length} clients`);
|
||||
return this.sessions.map((session: SmppSession) => {
|
||||
return session.serialize();
|
||||
});
|
||||
}
|
||||
serialize(): object {
|
||||
this.logger.log1(`Serializing ${this.sessions.length} clients`);
|
||||
return this.sessions.map((session: SmppSession) => {
|
||||
return session.serialize();
|
||||
});
|
||||
}
|
||||
|
||||
getExisting(arg: any): Promise<SmppSession> {
|
||||
return new Promise<SmppSession>((resolve, reject) => {
|
||||
this.logger.log1(`Looking for session with arg ${arg}...`);
|
||||
let session: SmppSession | undefined = this.sessions.find(this.comparatorFn.bind(this, arg));
|
||||
if (session) {
|
||||
this.logger.log1(`Found session with arg ${arg}`);
|
||||
resolve(session);
|
||||
} else {
|
||||
this.logger.log1(`Session with arg ${arg} not found`);
|
||||
reject(`Session with arg ${arg} not found`);
|
||||
}
|
||||
});
|
||||
}
|
||||
getExisting(arg: any): Promise<SmppSession> {
|
||||
return new Promise<SmppSession>((resolve, reject) => {
|
||||
this.logger.log1(`Looking for session with arg ${arg}...`);
|
||||
let session: SmppSession | undefined = this.sessions.find(this.comparatorFn.bind(this, arg));
|
||||
if (session) {
|
||||
this.logger.log1(`Found session with arg ${arg}`);
|
||||
resolve(session);
|
||||
} else {
|
||||
this.logger.log1(`Session with arg ${arg} not found`);
|
||||
reject(`Session with arg ${arg} not found`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -12,235 +12,235 @@ const NanoTimer = require("nanotimer");
|
||||
const smpp = require("smpp");
|
||||
|
||||
export default abstract class SmppSession {
|
||||
readonly EVENT: any = {
|
||||
STATUS_CHANGED: "STATUS_CHANGED",
|
||||
STATE_CHANGED: "STATE_CHANGED",
|
||||
ANY_PDU_TX: "ANY_PDU_TX",
|
||||
ANY_PDU_RX: "ANY_PDU_RX",
|
||||
MESSAGE_SEND_COUNTER_UPDATE_EVENT: "MESSAGE_SEND_COUNTER_UPDATE_EVENT",
|
||||
};
|
||||
abstract STATUSES: string[];
|
||||
readonly EVENT: any = {
|
||||
STATUS_CHANGED: "STATUS_CHANGED",
|
||||
STATE_CHANGED: "STATE_CHANGED",
|
||||
ANY_PDU_TX: "ANY_PDU_TX",
|
||||
ANY_PDU_RX: "ANY_PDU_RX",
|
||||
MESSAGE_SEND_COUNTER_UPDATE_EVENT: "MESSAGE_SEND_COUNTER_UPDATE_EVENT",
|
||||
};
|
||||
abstract STATUSES: string[];
|
||||
|
||||
processors: { [key: string]: PduProcessor[] } = {};
|
||||
readonly UPDATE_WS: string = "UPDATE_WS";
|
||||
readonly eventEmitter: EventEmitter = new EventEmitter();
|
||||
readonly logger: Logger = new Logger(this.constructor.name);
|
||||
readonly sendTimer: any = new NanoTimer();
|
||||
readonly counterUpdateTimer: any = new NanoTimer();
|
||||
readonly MESSAGE_SEND_UPDATE_DELAY: number = Number(process.env.MESSAGE_SEND_UPDATE_DELAY) || 500;
|
||||
processors: { [key: string]: PduProcessor[] } = {};
|
||||
readonly UPDATE_WS: string = "UPDATE_WS";
|
||||
readonly eventEmitter: EventEmitter = new EventEmitter();
|
||||
readonly logger: Logger = new Logger(this.constructor.name);
|
||||
readonly sendTimer: any = new NanoTimer();
|
||||
readonly counterUpdateTimer: any = new NanoTimer();
|
||||
readonly MESSAGE_SEND_UPDATE_DELAY: number = Number(process.env.MESSAGE_SEND_UPDATE_DELAY) || 500;
|
||||
|
||||
protected constructor() {
|
||||
this.eventEmitter.on(this.EVENT.STATE_CHANGED, () => this.updateWs(this.EVENT.STATE_CHANGED));
|
||||
this.eventEmitter.on(this.EVENT.STATUS_CHANGED, () => this.updateWs(this.EVENT.STATUS_CHANGED));
|
||||
this.eventEmitter.on(this.EVENT.ANY_PDU_TX, (pdu: any) => this.updateWs(this.EVENT.ANY_PDU_TX, [pdu]));
|
||||
this.eventEmitter.on(this.EVENT.ANY_PDU_RX, (pdu: any) => this.updateWs(this.EVENT.ANY_PDU_RX, [pdu]));
|
||||
this.eventEmitter.on(this.EVENT.MESSAGE_SEND_COUNTER_UPDATE_EVENT, (count: number) => this.updateWs(this.EVENT.MESSAGE_SEND_COUNTER_UPDATE_EVENT, [count]));
|
||||
protected constructor() {
|
||||
this.eventEmitter.on(this.EVENT.STATE_CHANGED, () => this.updateWs(this.EVENT.STATE_CHANGED));
|
||||
this.eventEmitter.on(this.EVENT.STATUS_CHANGED, () => this.updateWs(this.EVENT.STATUS_CHANGED));
|
||||
this.eventEmitter.on(this.EVENT.ANY_PDU_TX, (pdu: any) => this.updateWs(this.EVENT.ANY_PDU_TX, [pdu]));
|
||||
this.eventEmitter.on(this.EVENT.ANY_PDU_RX, (pdu: any) => this.updateWs(this.EVENT.ANY_PDU_RX, [pdu]));
|
||||
this.eventEmitter.on(this.EVENT.MESSAGE_SEND_COUNTER_UPDATE_EVENT, (count: number) => this.updateWs(this.EVENT.MESSAGE_SEND_COUNTER_UPDATE_EVENT, [count]));
|
||||
|
||||
this.processors[Preprocessor.name] = [];
|
||||
this.processors[Postprocessor.name] = [];
|
||||
}
|
||||
this.processors[Preprocessor.name] = [];
|
||||
this.processors[Postprocessor.name] = [];
|
||||
}
|
||||
|
||||
get appliedProcessors(): PduProcessor[] {
|
||||
return this.processors[Preprocessor.name].concat(this.processors[Postprocessor.name]);
|
||||
}
|
||||
get appliedProcessors(): PduProcessor[] {
|
||||
return this.processors[Preprocessor.name].concat(this.processors[Postprocessor.name]);
|
||||
}
|
||||
|
||||
abstract _username: string;
|
||||
abstract _username: string;
|
||||
|
||||
get username(): string {
|
||||
return this._username;
|
||||
}
|
||||
get username(): string {
|
||||
return this._username;
|
||||
}
|
||||
|
||||
set username(username: string) {
|
||||
this._username = username;
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
set username(username: string) {
|
||||
this._username = username;
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
|
||||
abstract _password: string;
|
||||
abstract _password: string;
|
||||
|
||||
get password(): string {
|
||||
return this._password;
|
||||
}
|
||||
get password(): string {
|
||||
return this._password;
|
||||
}
|
||||
|
||||
set password(password: string) {
|
||||
this._password = password;
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
set password(password: string) {
|
||||
this._password = password;
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
|
||||
abstract _id: number;
|
||||
abstract _id: number;
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
abstract _status: string;
|
||||
abstract _status: string;
|
||||
|
||||
get status(): string {
|
||||
return this._status;
|
||||
}
|
||||
get status(): string {
|
||||
return this._status;
|
||||
}
|
||||
|
||||
set status(status: string) {
|
||||
this._status = status;
|
||||
this.eventEmitter.emit(this.EVENT.STATUS_CHANGED, this.status);
|
||||
}
|
||||
set status(status: string) {
|
||||
this._status = status;
|
||||
this.eventEmitter.emit(this.EVENT.STATUS_CHANGED, this.status);
|
||||
}
|
||||
|
||||
abstract _defaultSingleJob: Job;
|
||||
abstract _defaultSingleJob: Job;
|
||||
|
||||
get defaultSingleJob(): Job {
|
||||
return this._defaultSingleJob;
|
||||
}
|
||||
get defaultSingleJob(): Job {
|
||||
return this._defaultSingleJob;
|
||||
}
|
||||
|
||||
set defaultSingleJob(job: Job) {
|
||||
this._defaultSingleJob = job;
|
||||
job.on(Job.STATE_CHANGED, this.eventJobUpdated);
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
set defaultSingleJob(job: Job) {
|
||||
this._defaultSingleJob = job;
|
||||
job.on(Job.STATE_CHANGED, this.eventJobUpdated);
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
|
||||
abstract _defaultMultipleJob: Job;
|
||||
abstract _defaultMultipleJob: Job;
|
||||
|
||||
get defaultMultipleJob(): Job {
|
||||
return this._defaultMultipleJob;
|
||||
}
|
||||
get defaultMultipleJob(): Job {
|
||||
return this._defaultMultipleJob;
|
||||
}
|
||||
|
||||
set defaultMultipleJob(job: Job) {
|
||||
this._defaultMultipleJob = job;
|
||||
job.on(Job.STATE_CHANGED, this.eventJobUpdated);
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
set defaultMultipleJob(job: Job) {
|
||||
this._defaultMultipleJob = job;
|
||||
job.on(Job.STATE_CHANGED, this.eventJobUpdated);
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
|
||||
setStatus(statusIndex: number) {
|
||||
this._status = this.STATUSES[statusIndex];
|
||||
this.eventEmitter.emit(this.EVENT.STATUS_CHANGED, this.status);
|
||||
}
|
||||
setStatus(statusIndex: number) {
|
||||
this._status = this.STATUSES[statusIndex];
|
||||
this.eventEmitter.emit(this.EVENT.STATUS_CHANGED, this.status);
|
||||
}
|
||||
|
||||
abstract sendPdu(pdu: object, force?: boolean): Promise<object>;
|
||||
abstract sendPdu(pdu: object, force?: boolean): Promise<object>;
|
||||
|
||||
doSendPdu(pdu: PDU, session: any): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
let characterSizeBits: number = LongSmsProcessor.getCharacterSizeForEncoding(pdu);
|
||||
let maxMessageLength: number = LongSmsProcessor.maxMessageSizeBits / characterSizeBits;
|
||||
if (!!pdu.short_message && pdu.short_message.length > maxMessageLength) {
|
||||
pdu.short_message = pdu.short_message.substring(0, maxMessageLength);
|
||||
}
|
||||
session.send(pdu, (reply: any) => resolve(reply));
|
||||
this.eventEmitter.emit(this.EVENT.ANY_PDU_TX, pdu);
|
||||
});
|
||||
}
|
||||
doSendPdu(pdu: PDU, session: any): Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
let characterSizeBits: number = LongSmsProcessor.getCharacterSizeForEncoding(pdu);
|
||||
let maxMessageLength: number = LongSmsProcessor.maxMessageSizeBits / characterSizeBits;
|
||||
if (!!pdu.short_message && pdu.short_message.length > maxMessageLength) {
|
||||
pdu.short_message = pdu.short_message.substring(0, maxMessageLength);
|
||||
}
|
||||
session.send(pdu, (reply: any) => resolve(reply));
|
||||
this.eventEmitter.emit(this.EVENT.ANY_PDU_TX, pdu);
|
||||
});
|
||||
}
|
||||
|
||||
abstract destroy(): void;
|
||||
abstract destroy(): void;
|
||||
|
||||
sendSingle(job: Job): Promise<object> {
|
||||
return this.sendPdu(job.pdu);
|
||||
}
|
||||
sendSingle(job: Job): Promise<object> {
|
||||
return this.sendPdu(job.pdu);
|
||||
}
|
||||
|
||||
sendSingleDefault(): Promise<object> {
|
||||
return this.sendSingle(this.defaultSingleJob);
|
||||
}
|
||||
sendSingleDefault(): Promise<object> {
|
||||
return this.sendSingle(this.defaultSingleJob);
|
||||
}
|
||||
|
||||
abstract sendMultiple(job: Job): Promise<void>;
|
||||
abstract sendMultiple(job: Job): Promise<void>;
|
||||
|
||||
sendMultipleDefault(): Promise<void> {
|
||||
return this.sendMultiple(this.defaultMultipleJob);
|
||||
}
|
||||
sendMultipleDefault(): Promise<void> {
|
||||
return this.sendMultiple(this.defaultMultipleJob);
|
||||
}
|
||||
|
||||
cancelSendInterval(): void {
|
||||
this.sendTimer.clearInterval();
|
||||
this.counterUpdateTimer.clearInterval();
|
||||
this.setStatus(this.STATUSES.length - 2);
|
||||
}
|
||||
cancelSendInterval(): void {
|
||||
this.sendTimer.clearInterval();
|
||||
this.counterUpdateTimer.clearInterval();
|
||||
this.setStatus(this.STATUSES.length - 2);
|
||||
}
|
||||
|
||||
abstract close(): Promise<void>;
|
||||
abstract close(): Promise<void>;
|
||||
|
||||
serialize(): object {
|
||||
let obj = {
|
||||
id: this._id,
|
||||
username: this._username,
|
||||
password: this._password,
|
||||
status: this._status,
|
||||
defaultSingleJob: this._defaultSingleJob.serialize(),
|
||||
defaultMultipleJob: this._defaultMultipleJob.serialize(),
|
||||
preprocessors: this.processors.Preprocessor.map((p: PduProcessor) => p.serialize()),
|
||||
postprocessors: this.processors.Postprocessor.map((p: PduProcessor) => p.serialize()),
|
||||
availablePreprocessors: ProcessorManager.getPreprocessorsForType(this.constructor.name).map((p: PduProcessor) => p.serialize()),
|
||||
availablePostprocessors: ProcessorManager.getPostprocessorsForType(this.constructor.name).map((p: PduProcessor) => p.serialize()),
|
||||
};
|
||||
return this.postSerialize(obj);
|
||||
}
|
||||
serialize(): object {
|
||||
let obj = {
|
||||
id: this._id,
|
||||
username: this._username,
|
||||
password: this._password,
|
||||
status: this._status,
|
||||
defaultSingleJob: this._defaultSingleJob.serialize(),
|
||||
defaultMultipleJob: this._defaultMultipleJob.serialize(),
|
||||
preprocessors: this.processors.Preprocessor.map((p: PduProcessor) => p.serialize()),
|
||||
postprocessors: this.processors.Postprocessor.map((p: PduProcessor) => p.serialize()),
|
||||
availablePreprocessors: ProcessorManager.getPreprocessorsForType(this.constructor.name).map((p: PduProcessor) => p.serialize()),
|
||||
availablePostprocessors: ProcessorManager.getPostprocessorsForType(this.constructor.name).map((p: PduProcessor) => p.serialize()),
|
||||
};
|
||||
return this.postSerialize(obj);
|
||||
}
|
||||
|
||||
abstract postSerialize(obj: object): object;
|
||||
abstract postSerialize(obj: object): object;
|
||||
|
||||
on(event: string, callback: (...args: any[]) => void): void {
|
||||
this.eventEmitter.on(event, callback);
|
||||
}
|
||||
on(event: string, callback: (...args: any[]) => void): void {
|
||||
this.eventEmitter.on(event, callback);
|
||||
}
|
||||
|
||||
updateWs(event: string, args?: any[]): void {
|
||||
this.logger.log1(`Update WS: ${event}`);
|
||||
let message: WSMessage = {
|
||||
type: event,
|
||||
identifier: `${this.constructor.name}:${this.id.toString()}`
|
||||
};
|
||||
switch (event) {
|
||||
case this.EVENT.STATE_CHANGED:
|
||||
message.data = this.serialize();
|
||||
break;
|
||||
case this.EVENT.STATUS_CHANGED:
|
||||
message.data = this.status;
|
||||
break;
|
||||
case this.EVENT.ANY_PDU_RX:
|
||||
case this.EVENT.ANY_PDU_TX:
|
||||
message.data = args![0];
|
||||
break;
|
||||
case this.EVENT.MESSAGE_SEND_COUNTER_UPDATE_EVENT:
|
||||
message.data = args![0];
|
||||
break;
|
||||
}
|
||||
this.eventEmitter.emit(this.UPDATE_WS, message);
|
||||
}
|
||||
updateWs(event: string, args?: any[]): void {
|
||||
this.logger.log1(`Update WS: ${event}`);
|
||||
let message: WSMessage = {
|
||||
type: event,
|
||||
identifier: `${this.constructor.name}:${this.id.toString()}`
|
||||
};
|
||||
switch (event) {
|
||||
case this.EVENT.STATE_CHANGED:
|
||||
message.data = this.serialize();
|
||||
break;
|
||||
case this.EVENT.STATUS_CHANGED:
|
||||
message.data = this.status;
|
||||
break;
|
||||
case this.EVENT.ANY_PDU_RX:
|
||||
case this.EVENT.ANY_PDU_TX:
|
||||
message.data = args![0];
|
||||
break;
|
||||
case this.EVENT.MESSAGE_SEND_COUNTER_UPDATE_EVENT:
|
||||
message.data = args![0];
|
||||
break;
|
||||
}
|
||||
this.eventEmitter.emit(this.UPDATE_WS, message);
|
||||
}
|
||||
|
||||
eventJobUpdated(): void {
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
eventJobUpdated(): void {
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
|
||||
attachPreprocessor(processor: PduProcessor): void {
|
||||
this.attachProcessor(processor, this.processors.Preprocessor);
|
||||
}
|
||||
attachPreprocessor(processor: PduProcessor): void {
|
||||
this.attachProcessor(processor, this.processors.Preprocessor);
|
||||
}
|
||||
|
||||
attachPostprocessor(processor: PduProcessor): void {
|
||||
this.attachProcessor(processor, this.processors.Postprocessor);
|
||||
}
|
||||
attachPostprocessor(processor: PduProcessor): void {
|
||||
this.attachProcessor(processor, this.processors.Postprocessor);
|
||||
}
|
||||
|
||||
detachPreprocessor(processor: PduProcessor): void {
|
||||
this.detachProcessor(processor, this.processors.Preprocessor);
|
||||
}
|
||||
detachPreprocessor(processor: PduProcessor): void {
|
||||
this.detachProcessor(processor, this.processors.Preprocessor);
|
||||
}
|
||||
|
||||
detachPostprocessor(processor: PduProcessor): void {
|
||||
this.detachProcessor(processor, this.processors.Postprocessor);
|
||||
}
|
||||
detachPostprocessor(processor: PduProcessor): void {
|
||||
this.detachProcessor(processor, this.processors.Postprocessor);
|
||||
}
|
||||
|
||||
eventAnyPdu(session: any, pdu: PDU): Promise<any> {
|
||||
if (!!pdu) {
|
||||
this.eventEmitter.emit(this.EVENT.ANY_PDU_RX, pdu);
|
||||
// console.log("IS PDU TIME");
|
||||
this.logger.log6(pdu);
|
||||
this.processors.Postprocessor.forEach((processor: PduProcessor) => processor.processPdu(session, pdu, this));
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
eventAnyPdu(session: any, pdu: PDU): Promise<any> {
|
||||
if (!!pdu) {
|
||||
this.eventEmitter.emit(this.EVENT.ANY_PDU_RX, pdu);
|
||||
// console.log("IS PDU TIME");
|
||||
this.logger.log6(pdu);
|
||||
this.processors.Postprocessor.forEach((processor: PduProcessor) => processor.processPdu(session, pdu, this));
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
private detachProcessor(processor: PduProcessor, array: PduProcessor[]): void {
|
||||
if (array.indexOf(processor) >= 0) {
|
||||
array.splice(array.indexOf(processor), 1);
|
||||
this.logger.log1(`Detaching PDU processor: ${processor.constructor.name}-${this.id}, now active: ${array.length} processors`);
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
}
|
||||
private detachProcessor(processor: PduProcessor, array: PduProcessor[]): void {
|
||||
if (array.indexOf(processor) >= 0) {
|
||||
array.splice(array.indexOf(processor), 1);
|
||||
this.logger.log1(`Detaching PDU processor: ${processor.constructor.name}-${this.id}, now active: ${array.length} processors`);
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
}
|
||||
}
|
||||
|
||||
private attachProcessor(processor: PduProcessor, array: PduProcessor[]): void {
|
||||
if (array.indexOf(processor) === -1) {
|
||||
array.push(processor);
|
||||
this.logger.log1(`Attaching PDU processor: ${processor.constructor.name}-${this.id}, now active: ${array.length} processors`);
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
} else {
|
||||
this.logger.log1(`PDU processor: ${processor.constructor.name}-${this.id} already attached to session`);
|
||||
}
|
||||
}
|
||||
private attachProcessor(processor: PduProcessor, array: PduProcessor[]): void {
|
||||
if (array.indexOf(processor) === -1) {
|
||||
array.push(processor);
|
||||
this.logger.log1(`Attaching PDU processor: ${processor.constructor.name}-${this.id}, now active: ${array.length} processors`);
|
||||
this.eventEmitter.emit(this.EVENT.STATE_CHANGED, this.serialize());
|
||||
} else {
|
||||
this.logger.log1(`PDU processor: ${processor.constructor.name}-${this.id} already attached to session`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,70 +5,70 @@ import SmppSession from "../SmppSession";
|
||||
import ZlibCoder from "../ZlibCoder";
|
||||
|
||||
export default class ClientSet {
|
||||
identifier: string;
|
||||
private clients: any[];
|
||||
private readonly type: string;
|
||||
private readonly sessionId: number;
|
||||
private readonly logger: Logger;
|
||||
private readonly relevantSessionManager: SessionManager | undefined;
|
||||
identifier: string;
|
||||
private clients: any[];
|
||||
private readonly type: string;
|
||||
private readonly sessionId: number;
|
||||
private readonly logger: Logger;
|
||||
private readonly relevantSessionManager: SessionManager | undefined;
|
||||
|
||||
constructor(identifier: string, sessionManagers: SessionManager[]) {
|
||||
this.clients = [];
|
||||
this.identifier = identifier;
|
||||
constructor(identifier: string, sessionManagers: SessionManager[]) {
|
||||
this.clients = [];
|
||||
this.identifier = identifier;
|
||||
|
||||
let data: string[] = identifier.split(':');
|
||||
this.type = data[0];
|
||||
this.sessionId = parseInt(data[1]);
|
||||
let data: string[] = identifier.split(':');
|
||||
this.type = data[0];
|
||||
this.sessionId = parseInt(data[1]);
|
||||
|
||||
this.logger = new Logger(`ClientSet-${this.type}-${this.sessionId}`);
|
||||
this.logger.log1(`Created client set for ${this.type} ${this.sessionId}`);
|
||||
this.logger = new Logger(`ClientSet-${this.type}-${this.sessionId}`);
|
||||
this.logger.log1(`Created client set for ${this.type} ${this.sessionId}`);
|
||||
|
||||
this.relevantSessionManager = sessionManagers.find(sm => sm.identifier === this.type);
|
||||
if (!this.relevantSessionManager) {
|
||||
this.logger.log1(`No session manager found for type ${this.type}`);
|
||||
return;
|
||||
}
|
||||
if (this.relevantSessionManager) {
|
||||
this.relevantSessionManager.getSessions().then((sessions) => {
|
||||
sessions.forEach((session) => {
|
||||
this.attachListener(session);
|
||||
});
|
||||
});
|
||||
}
|
||||
this.relevantSessionManager.on(this.relevantSessionManager.SESSION_ADDED_EVENT, this.eventOnSessionAdded.bind(this));
|
||||
}
|
||||
this.relevantSessionManager = sessionManagers.find(sm => sm.identifier === this.type);
|
||||
if (!this.relevantSessionManager) {
|
||||
this.logger.log1(`No session manager found for type ${this.type}`);
|
||||
return;
|
||||
}
|
||||
if (this.relevantSessionManager) {
|
||||
this.relevantSessionManager.getSessions().then((sessions) => {
|
||||
sessions.forEach((session) => {
|
||||
this.attachListener(session);
|
||||
});
|
||||
});
|
||||
}
|
||||
this.relevantSessionManager.on(this.relevantSessionManager.SESSION_ADDED_EVENT, this.eventOnSessionAdded.bind(this));
|
||||
}
|
||||
|
||||
eventOnSessionAdded(sessionId: number): void {
|
||||
this.logger.log2(`Session added: ${sessionId}`);
|
||||
this.relevantSessionManager?.getSession(sessionId).then((session) => {
|
||||
this.attachListener(session);
|
||||
})
|
||||
}
|
||||
eventOnSessionAdded(sessionId: number): void {
|
||||
this.logger.log2(`Session added: ${sessionId}`);
|
||||
this.relevantSessionManager?.getSession(sessionId).then((session) => {
|
||||
this.attachListener(session);
|
||||
})
|
||||
}
|
||||
|
||||
add(ws: any): void {
|
||||
this.logger.log2(`Added client`);
|
||||
this.clients.push(ws);
|
||||
ws.on('close', this.eventOnClose.bind(this, ws));
|
||||
}
|
||||
add(ws: any): void {
|
||||
this.logger.log2(`Added client`);
|
||||
this.clients.push(ws);
|
||||
ws.on('close', this.eventOnClose.bind(this, ws));
|
||||
}
|
||||
|
||||
eventOnClose(ws: any): void {
|
||||
this.logger.log2(`Removed client`);
|
||||
this.clients.splice(this.clients.indexOf(ws), 1);
|
||||
}
|
||||
eventOnClose(ws: any): void {
|
||||
this.logger.log2(`Removed client`);
|
||||
this.clients.splice(this.clients.indexOf(ws), 1);
|
||||
}
|
||||
|
||||
notifyClients(message: WSMessage) {
|
||||
if (message.identifier !== this.identifier) return;
|
||||
let textMessage: string = JSON.stringify(message);
|
||||
let compressedMessage = ZlibCoder.compress(textMessage);
|
||||
if (this.clients.length > 0) {
|
||||
this.logger.log2(`Notifying clients: ${message}`);
|
||||
this.clients.forEach((ws) => {
|
||||
ws.send(compressedMessage);
|
||||
});
|
||||
}
|
||||
}
|
||||
notifyClients(message: WSMessage) {
|
||||
if (message.identifier !== this.identifier) return;
|
||||
let textMessage: string = JSON.stringify(message);
|
||||
let compressedMessage = ZlibCoder.compress(textMessage);
|
||||
if (this.clients.length > 0) {
|
||||
this.logger.log2(`Notifying clients: ${message}`);
|
||||
this.clients.forEach((ws) => {
|
||||
ws.send(compressedMessage);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private attachListener(session: SmppSession) {
|
||||
session.on(session.UPDATE_WS, (message: WSMessage) => this.notifyClients(message));
|
||||
}
|
||||
private attachListener(session: SmppSession) {
|
||||
session.on(session.UPDATE_WS, (message: WSMessage) => this.notifyClients(message));
|
||||
}
|
||||
}
|
@@ -7,45 +7,45 @@ const WebSocket = require("ws");
|
||||
const WS_SERVER_PORT: number = Number(process.env.WS_SERVER_PORT) || 8191;
|
||||
|
||||
export default class WSServer {
|
||||
private readonly clients: ClientSet[];
|
||||
private readonly unknownClients: any[];
|
||||
private readonly server: any;
|
||||
private readonly logger: Logger;
|
||||
private readonly sessionManagers: SessionManager[];
|
||||
private readonly clients: ClientSet[];
|
||||
private readonly unknownClients: any[];
|
||||
private readonly server: any;
|
||||
private readonly logger: Logger;
|
||||
private readonly sessionManagers: SessionManager[];
|
||||
|
||||
constructor(sessionManagers: SessionManager[]) {
|
||||
this.clients = [];
|
||||
this.unknownClients = [];
|
||||
this.server = new WebSocket.Server({port: WS_SERVER_PORT});
|
||||
this.sessionManagers = sessionManagers;
|
||||
this.logger = new Logger("WSServer");
|
||||
this.server.on('connection', this.eventOnConnection.bind(this));
|
||||
this.logger.log1(`WSServer listening at ws://localhost:${WS_SERVER_PORT}`);
|
||||
}
|
||||
constructor(sessionManagers: SessionManager[]) {
|
||||
this.clients = [];
|
||||
this.unknownClients = [];
|
||||
this.server = new WebSocket.Server({port: WS_SERVER_PORT});
|
||||
this.sessionManagers = sessionManagers;
|
||||
this.logger = new Logger("WSServer");
|
||||
this.server.on('connection', this.eventOnConnection.bind(this));
|
||||
this.logger.log1(`WSServer listening at ws://localhost:${WS_SERVER_PORT}`);
|
||||
}
|
||||
|
||||
private eventOnConnection(ws: WebSocket): void {
|
||||
this.logger.log1("New connection");
|
||||
this.unknownClients.push(ws);
|
||||
// @ts-ignore
|
||||
ws.on('message', this.eventOnMessage.bind(this, ws));
|
||||
// @ts-ignore
|
||||
ws.on('close', this.eventOnClose.bind(this, ws));
|
||||
}
|
||||
private eventOnConnection(ws: WebSocket): void {
|
||||
this.logger.log1("New connection");
|
||||
this.unknownClients.push(ws);
|
||||
// @ts-ignore
|
||||
ws.on('message', this.eventOnMessage.bind(this, ws));
|
||||
// @ts-ignore
|
||||
ws.on('close', this.eventOnClose.bind(this, ws));
|
||||
}
|
||||
|
||||
private eventOnMessage(ws: any, message: string): void {
|
||||
this.logger.log1("New message");
|
||||
message = String(message);
|
||||
this.unknownClients.splice(this.unknownClients.indexOf(ws), 1);
|
||||
let clientSet: ClientSet | undefined = this.clients.find((clientSet: ClientSet) => clientSet.identifier === message);
|
||||
if (!clientSet) {
|
||||
clientSet = new ClientSet(message, this.sessionManagers);
|
||||
this.clients.push(clientSet);
|
||||
}
|
||||
clientSet.add(ws);
|
||||
}
|
||||
private eventOnMessage(ws: any, message: string): void {
|
||||
this.logger.log1("New message");
|
||||
message = String(message);
|
||||
this.unknownClients.splice(this.unknownClients.indexOf(ws), 1);
|
||||
let clientSet: ClientSet | undefined = this.clients.find((clientSet: ClientSet) => clientSet.identifier === message);
|
||||
if (!clientSet) {
|
||||
clientSet = new ClientSet(message, this.sessionManagers);
|
||||
this.clients.push(clientSet);
|
||||
}
|
||||
clientSet.add(ws);
|
||||
}
|
||||
|
||||
private eventOnClose(ws: any): void {
|
||||
this.logger.log1("Connection closed");
|
||||
this.unknownClients.splice(this.unknownClients.indexOf(ws), 1);
|
||||
}
|
||||
private eventOnClose(ws: any): void {
|
||||
this.logger.log1("Connection closed");
|
||||
this.unknownClients.splice(this.unknownClients.indexOf(ws), 1);
|
||||
}
|
||||
}
|
@@ -1,11 +1,11 @@
|
||||
const zlib = require("zlib");
|
||||
|
||||
export default class ZlibCoder {
|
||||
static compress(input: string): Buffer {
|
||||
return zlib.deflateSync(input).toString('base64');
|
||||
}
|
||||
static compress(input: string): Buffer {
|
||||
return zlib.deflateSync(input).toString('base64');
|
||||
}
|
||||
|
||||
static decompress(input: Buffer): string {
|
||||
return zlib.decompress(input).toString();
|
||||
}
|
||||
static decompress(input: Buffer): string {
|
||||
return zlib.decompress(input).toString();
|
||||
}
|
||||
}
|
25
src/main.js
Normal file
25
src/main.js
Normal file
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var CenterSessionManager_1 = require("./Center/CenterSessionManager");
|
||||
var ClientSessionManager_1 = require("./Client/ClientSessionManager");
|
||||
var HttpServer_1 = require("./HttpServer/HttpServer");
|
||||
var Logger_1 = require("./Logger");
|
||||
var ProcessorManager_1 = require("./PDUProcessor/ProcessorManager");
|
||||
var WSServer_1 = require("./WS/WSServer");
|
||||
var PDU = require("smpp").PDU;
|
||||
var logger = new Logger_1.default("main");
|
||||
var pm = new ProcessorManager_1.default();
|
||||
var clientManager = new ClientSessionManager_1.default();
|
||||
var centerManager = new CenterSessionManager_1.default();
|
||||
var wss = new WSServer_1.default([clientManager, centerManager]);
|
||||
var httpServer = new HttpServer_1.default(clientManager, centerManager);
|
||||
function cleanup() {
|
||||
logger.log1("Cleaning up...");
|
||||
clientManager.cleanup();
|
||||
centerManager.cleanup();
|
||||
process.exit(0);
|
||||
}
|
||||
process.on('exit', cleanup);
|
||||
process.on('SIGINT', cleanup);
|
||||
process.on('SIGUSR1', cleanup);
|
||||
process.on('SIGUSR2', cleanup);
|
@@ -17,10 +17,10 @@ let wss: WSServer = new WSServer([clientManager, centerManager]);
|
||||
let httpServer: HttpServer = new HttpServer(clientManager, centerManager);
|
||||
|
||||
function cleanup(): void {
|
||||
logger.log1("Cleaning up...");
|
||||
clientManager.cleanup();
|
||||
centerManager.cleanup();
|
||||
process.exit(0);
|
||||
logger.log1("Cleaning up...");
|
||||
clientManager.cleanup();
|
||||
centerManager.cleanup();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
process.on('exit', cleanup);
|
||||
|
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"moduleResolution": "node",
|
||||
"strict": false,
|
||||
"verbatimModuleSyntax": false,
|
||||
"noUncheckedIndexedAccess": false,
|
||||
|
||||
"moduleResolution": "NodeNext",
|
||||
"module": "NodeNext",
|
||||
"target": "ESNext",
|
||||
|
||||
"esModuleInterop": true,
|
||||
"noImplicitAny": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"exclude": [
|
||||
"./node_modules"
|
||||
]
|
||||
"include": ["src/**/*", "src/main.ts"]
|
||||
}
|
||||
|
13
tsup.config.ts
Normal file
13
tsup.config.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/main.ts'],
|
||||
dts: false,
|
||||
splitting: false,
|
||||
sourcemap: false,
|
||||
outDir: 'build',
|
||||
clean: true,
|
||||
minify: true,
|
||||
target: ['esnext'],
|
||||
format: ['cjs']
|
||||
});
|
61
workfile.js
Normal file
61
workfile.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import { connect } from "smpp";
|
||||
import fs from "fs";
|
||||
|
||||
const optionsFile = "smpp_tester_options.json";
|
||||
|
||||
const exampleSession = {
|
||||
url: "smpp://172.17.77.203:4445",
|
||||
connection_count: 1,
|
||||
system_id: "snt",
|
||||
password: "snt",
|
||||
source_addr: "44455",
|
||||
destination_addr: "test123",
|
||||
short_message: "SNT BENCHMARK!",
|
||||
message_count: 100,
|
||||
};
|
||||
|
||||
if (!fs.existsSync(optionsFile)) {
|
||||
fs.writeFileSync(optionsFile, JSON.stringify([exampleSession], null, 4));
|
||||
process.exit(1);
|
||||
}
|
||||
const options = fs.readFileSync(optionsFile, "utf8") ?? "[]";
|
||||
const sessions = JSON.parse(options);
|
||||
const smppSessions = [];
|
||||
|
||||
for (const session of sessions) {
|
||||
for (let i = 0; i < session.connection_count; i++) {
|
||||
const smppSession = connect(
|
||||
{
|
||||
url: session.url,
|
||||
auto_enquire_link_period: 10000,
|
||||
debug: true,
|
||||
},
|
||||
function () {
|
||||
smppSession.bind_transceiver({
|
||||
system_id: session.system_id,
|
||||
password: session.password,
|
||||
});
|
||||
}
|
||||
);
|
||||
smppSessions.push({ properties: session, session: smppSession });
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
for (const session of smppSessions) {
|
||||
for (let i = 0; i < session.properties.message_count; i++) {
|
||||
session.session.submit_sm(
|
||||
{
|
||||
source_addr: session.properties.source_addr,
|
||||
destination_addr: session.properties.destination_addr,
|
||||
short_message: session.properties.short_message,
|
||||
},
|
||||
function (pdu) {
|
||||
if (pdu.command_status === 0) {
|
||||
console.log(pdu.message_id);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}, 1000);
|
Reference in New Issue
Block a user