From 12dd92e9805a682dd0866efa97502c66d8d249dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Majdand=C5=BEi=C4=87?= Date: Thu, 6 Apr 2023 20:04:38 +0200 Subject: [PATCH] Implement longSms processor --- src/Center/Center.ts | 2 +- src/Client/Client.ts | 2 +- .../Preprocessor/Client/LongSmsProcessor.ts | 80 +++++++++++++++++++ src/PDUProcessor/ProcessorManager.ts | 4 +- 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 src/PDUProcessor/Preprocessor/Client/LongSmsProcessor.ts diff --git a/src/Center/Center.ts b/src/Center/Center.ts index 9118343..5630a64 100644 --- a/src/Center/Center.ts +++ b/src/Center/Center.ts @@ -86,7 +86,7 @@ export default class Center extends SmppSession { 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.processors.Preprocessor.forEach((processor: PduProcessor) => processor.processPdu(session, pduCopy, this)); this.doSendPdu(pduCopy, session).then((replyPdu: any) => { resolve(replyPdu); }); diff --git a/src/Client/Client.ts b/src/Client/Client.ts index a53322e..2059e53 100644 --- a/src/Client/Client.ts +++ b/src/Client/Client.ts @@ -147,7 +147,7 @@ export default class Client extends SmppSession { } // Is this expensive...? let pduCopy = new smpp.PDU(pdu.command, {...pdu}); - this.processors.Preprocessor.forEach((processor: PduProcessor) => processor.processPdu(this.session, pduCopy)); + 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); diff --git a/src/PDUProcessor/Preprocessor/Client/LongSmsProcessor.ts b/src/PDUProcessor/Preprocessor/Client/LongSmsProcessor.ts new file mode 100644 index 0000000..de524ae --- /dev/null +++ b/src/PDUProcessor/Preprocessor/Client/LongSmsProcessor.ts @@ -0,0 +1,80 @@ +import {PDU} from "../../../CommonObjects"; +import SmppSession from "../../../SmppSession"; +import Preprocessor from "../Preprocessor"; + +const smpp = require('smpp'); + +export default class LongSmsProcessor extends Preprocessor { + 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); + } + + processPdu(session: any, pdu: PDU, entity?: SmppSession | undefined): Promise { + return new Promise((resolve, reject) => { + if (!!pdu.short_message) { + 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; + } + if (characterSizeBits) { + let splitMessage: string[] = []; + let message: string = pdu.short_message; + let messageLength: number = message.length; + let maxMessageLength: number = 1072 / characterSizeBits; + 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]); + + 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); + } + }); + } + } + }); + } +} \ No newline at end of file diff --git a/src/PDUProcessor/ProcessorManager.ts b/src/PDUProcessor/ProcessorManager.ts index aa39de4..2454a1b 100644 --- a/src/PDUProcessor/ProcessorManager.ts +++ b/src/PDUProcessor/ProcessorManager.ts @@ -12,6 +12,7 @@ import DeliverSmReplyProcessor from "./Postprocessor/Client/DeliverSmReplyProces import Postprocessor from "./Postprocessor/Postprocessor"; import DeliveryReceiptRequestProcessor from "./Preprocessor/Client/DeliveryReceiptRequestProcessor"; import DestinationEnumeratorProcessor from "./Preprocessor/Client/DestinationEnumeratorProcessor"; +import LongSmsProcessor from "./Preprocessor/Client/LongSmsProcessor"; import SourceEnumeratorProcessor from "./Preprocessor/Client/SourceEnumeratorProcessor"; import Preprocessor from "./Preprocessor/Preprocessor"; @@ -34,7 +35,8 @@ export default class ProcessorManager { ProcessorManager.preprocessors = [ new DestinationEnumeratorProcessor(Client.name), new SourceEnumeratorProcessor(Client.name), - new DeliveryReceiptRequestProcessor(Client.name) + new DeliveryReceiptRequestProcessor(Client.name), + new LongSmsProcessor(Client.name) ]; }