Fixed problem with UCS2 encoded long messages
This commit is contained in:
+9
-2
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
// More or less copied from https://github.com/farhadi/node-smpp
|
// More or less copied from https://github.com/farhadi/node-smpp
|
||||||
|
|
||||||
var iconv = require('iconv-lite'),
|
var log = require('winston'),
|
||||||
|
iconv = require('iconv-lite'),
|
||||||
encodings = {},
|
encodings = {},
|
||||||
filters = {},
|
filters = {},
|
||||||
tlvsById = {},
|
tlvsById = {},
|
||||||
@@ -135,7 +136,13 @@ types = {
|
|||||||
},
|
},
|
||||||
write: function(value, buffer, offset) {
|
write: function(value, buffer, offset) {
|
||||||
value = value || 0;
|
value = value || 0;
|
||||||
buffer.writeUInt8(value, offset);
|
|
||||||
|
try {
|
||||||
|
buffer.writeUInt8(value, offset);
|
||||||
|
} catch (err) {
|
||||||
|
log.error('larvitsmpp: lib/defs.js - Could not write integer value "' + value + '" on offset "' + offset + '" when buffer length is "' + buffer.length + '"');
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
size: function() {
|
size: function() {
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -357,6 +357,8 @@ function sendSms(smsOptions, callback) {
|
|||||||
|
|
||||||
// Check if we must split this message into multiple
|
// Check if we must split this message into multiple
|
||||||
if (utils.bitCount(smsOptions.message) > 1120) {
|
if (utils.bitCount(smsOptions.message) > 1120) {
|
||||||
|
log.debug('larvitsmpp: lib/session.js: sendSms() - Message larger than 1120 bits, send it as long message!');
|
||||||
|
|
||||||
this.sendLongSms(smsOptions, callback);
|
this.sendLongSms(smsOptions, callback);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
+38
-17
@@ -1,7 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var log = require('winston'),
|
var log = require('winston'),
|
||||||
defs = require('./defs');
|
defs = require('./defs'),
|
||||||
|
bundleMsgId = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calcualte cmdLength from object
|
* Calcualte cmdLength from object
|
||||||
@@ -115,15 +116,19 @@ function writeBuffer(obj, cmdLength, callback) {
|
|||||||
paramType = defs.cmds[obj.cmdName].params[param].type;
|
paramType = defs.cmds[obj.cmdName].params[param].type;
|
||||||
paramSize = paramType.size(obj.params[param]);
|
paramSize = paramType.size(obj.params[param]);
|
||||||
|
|
||||||
// Write parameter value to buffer using the types method write()
|
|
||||||
paramType.write(obj.params[param], buff, offset);
|
|
||||||
|
|
||||||
if (Buffer.isBuffer(obj.params[param])) {
|
if (Buffer.isBuffer(obj.params[param])) {
|
||||||
log.silly('larvitsmpp: lib/utils.js: writeBuffer() - Writing param "' + param + '" with content "' + obj.params[param].toString('hex') + '" and size "' + paramSize + '"');
|
log.silly('larvitsmpp: lib/utils.js: writeBuffer() - Writing param "' + param + '" with content "' + obj.params[param].toString('hex') + '" and size "' + paramSize + '"');
|
||||||
} else {
|
} else {
|
||||||
|
if (param === 'sm_length') {
|
||||||
|
log.silly('larvitsmpp: lib/utils.js: writeBuffer() - sm_length is calculated by short_message: "' + obj.params.short_message.toString('hex') + '"');
|
||||||
|
}
|
||||||
|
|
||||||
log.silly('larvitsmpp: lib/utils.js: writeBuffer() - Writing param "' + param + '" with content "' + obj.params[param] + '"');
|
log.silly('larvitsmpp: lib/utils.js: writeBuffer() - Writing param "' + param + '" with content "' + obj.params[param] + '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write parameter value to buffer using the types method write()
|
||||||
|
paramType.write(obj.params[param], buff, offset);
|
||||||
|
|
||||||
// Increase the offset for the next param
|
// Increase the offset for the next param
|
||||||
offset += paramSize;
|
offset += paramSize;
|
||||||
}
|
}
|
||||||
@@ -424,9 +429,7 @@ function objToPdu(obj, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeBuffer(obj, cmdLength, function(err, buff) {
|
writeBuffer(obj, cmdLength, callback);
|
||||||
callback(err, buff);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,7 +585,11 @@ function smppDate(jsDateObj) {
|
|||||||
* @return integer
|
* @return integer
|
||||||
*/
|
*/
|
||||||
function bitCount(msg, encoding) {
|
function bitCount(msg, encoding) {
|
||||||
if (encoding === 'ASCII' || defs.encodings.ASCII.match(msg)) {
|
if (defs.encodings[encoding] === undefined) {
|
||||||
|
encoding = defs.encodings.detect(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoding === 'ASCII') {
|
||||||
return defs.encodings.ASCII.encode(msg).length * 7; // * 7 since each character takes up 7 bits
|
return defs.encodings.ASCII.encode(msg).length * 7; // * 7 since each character takes up 7 bits
|
||||||
} else {
|
} else {
|
||||||
return defs.encodings.UCS2.encode(msg).length * 8; // * 8 since its encoded as 16-bits.
|
return defs.encodings.UCS2.encode(msg).length * 8; // * 8 since its encoded as 16-bits.
|
||||||
@@ -596,26 +603,40 @@ function bitCount(msg, encoding) {
|
|||||||
* @return array of buffers
|
* @return array of buffers
|
||||||
*/
|
*/
|
||||||
function splitMsg(msg) {
|
function splitMsg(msg) {
|
||||||
var msgPart = '',
|
var msgPart = '',
|
||||||
msgs = [],
|
msgs = [],
|
||||||
msgId = Math.floor(Math.random() * (255 - 0)), // This will identify this message "bundle"
|
encoding = defs.encodings.detect(msg),
|
||||||
encoding = defs.encodings.detect(msg),
|
totBitCount = bitCount(msg, encoding),
|
||||||
|
partBitCount,
|
||||||
udh,
|
udh,
|
||||||
i;
|
i;
|
||||||
|
|
||||||
// A single message could contain up to 1120 bits
|
// A single message could contain up to 1120 bits
|
||||||
// Return directly if the message fits into that
|
// Return directly if the message fits into that
|
||||||
if (bitCount(msg) < 1121) {
|
if (totBitCount < 1121) {
|
||||||
|
log.silly('larvitsmpp: lib/utils.js: splitMsg() - bitCount below 1121 (' + totBitCount + ') return only one part');
|
||||||
return [defs.encodings[encoding].encode(msg)];
|
return [defs.encodings[encoding].encode(msg)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bundleMsgId ++; // This will identify this message "bundle"
|
||||||
|
|
||||||
|
if (bundleMsgId === 256) {
|
||||||
|
bundleMsgId = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.silly('larvitsmpp: lib/utils.js: splitMsg() - bundleMsgId set to ' + bundleMsgId);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while (msg[i] !== undefined) {
|
while (msg[i] !== undefined) {
|
||||||
msgPart += msg[i];
|
msgPart += msg[i];
|
||||||
|
|
||||||
if (bitCount(msgPart, encoding) > 1072) {
|
partBitCount = bitCount(msgPart, encoding);
|
||||||
|
|
||||||
|
if (partBitCount > 1072) {
|
||||||
// We've reached the message limit
|
// We've reached the message limit
|
||||||
|
|
||||||
|
log.debug('larvitsmpp: lib/utils.js: splitMsg() - Msg part defined. partBitCount: ' + partBitCount + ' msgPart: "' + msgPart + '"');
|
||||||
|
|
||||||
// Add this msgPart minus the last character to the msgs array as an encoded buffer
|
// Add this msgPart minus the last character to the msgs array as an encoded buffer
|
||||||
msgs.push(defs.encodings[encoding].encode(msgPart.slice(0, - 1)));
|
msgs.push(defs.encodings[encoding].encode(msgPart.slice(0, - 1)));
|
||||||
|
|
||||||
@@ -641,7 +662,7 @@ function splitMsg(msg) {
|
|||||||
0x05, // Length of User Data Header, in this case 05.
|
0x05, // Length of User Data Header, in this case 05.
|
||||||
0x00, // Information Element Identifier, equal to 00 (Concatenated short messages, 8-bit reference number)
|
0x00, // Information Element Identifier, equal to 00 (Concatenated short messages, 8-bit reference number)
|
||||||
0x03, // Length of the header, excluding the first two fields; equal to 03
|
0x03, // Length of the header, excluding the first two fields; equal to 03
|
||||||
msgId, // CSMS reference number, must be same for all the SMS parts in the CSMS
|
bundleMsgId, // CSMS reference number, must be same for all the SMS parts in the CSMS
|
||||||
msgs.length, // Total number of parts. The value shall remain constant for every short message which makes up the concatenated short message. If the value is zero then the receiving entity shall ignore the whole information element
|
msgs.length, // Total number of parts. The value shall remain constant for every short message which makes up the concatenated short message. If the value is zero then the receiving entity shall ignore the whole information element
|
||||||
i + 1 // This part's number in the sequence. The value shall start at 1 and increment for every short message which makes up the concatenated short message.
|
i + 1 // This part's number in the sequence. The value shall start at 1 and increment for every short message which makes up the concatenated short message.
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -225,6 +225,72 @@ describe('Sessions', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should try sending a weirder long sms', function(done) {
|
||||||
|
portfinder.getPort(function(err, freePort) {
|
||||||
|
assert( ! err, 'Error should not be negative');
|
||||||
|
|
||||||
|
larvitsmpp.server({
|
||||||
|
'port': freePort
|
||||||
|
}, function(err, serverSession) {
|
||||||
|
assert( ! err, 'Error should not be negative');
|
||||||
|
|
||||||
|
serverSession.on('sms', function(sms) {
|
||||||
|
sms.smsId = 2344;
|
||||||
|
|
||||||
|
assert(sms.from === 'foo', 'SMS from should be "foo"');
|
||||||
|
assert(sms.to === '46709771337', 'SMS to should be "46709771337"');
|
||||||
|
assert(sms.message === 'K sKM8NYUuoVbORtCn€swWsvTZjbtYM1TceGJJouolLk4cOtlk7j dxWMI56Domdx2W!dHKjGBR5UsynmUnbp1ysRDCktBri WW2pxIWHv0P7H OVRZNw 6 DBzAqpnd7ZPslwNyi»x OuiNH0R!WM2DTo8ItysNDNe1eNnpLvahhRgv»TC y lvgFrmv4OiUTOP', 'SMS message should be correct');
|
||||||
|
assert(sms.dlr === false, 'DLR should be boolean false');
|
||||||
|
assert(sms.pduObjs[0].pduObj.cmdId === 4, 'SMS pduObj cmdId should be 4');
|
||||||
|
|
||||||
|
sms.sendResp(function(err, retPdus) {
|
||||||
|
assert( ! err, 'Error should not be negative');
|
||||||
|
|
||||||
|
assert(retPdus[0].toString('hex') === '00000017800000040000000000000002323334342d3100', 'Return PDU 0 is wrong');
|
||||||
|
assert(retPdus[1].toString('hex') === '00000017800000040000000000000003323334342d3200', 'Return PDU 1 is wrong');
|
||||||
|
assert(retPdus[2].toString('hex') === '00000017800000040000000000000004323334342d3300', 'Return PDU 2 is wrong');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
serverSession.on('close', function() {
|
||||||
|
// Manually destroy the server socket
|
||||||
|
serverSession.sock.destroy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
larvitsmpp.client({
|
||||||
|
'port': freePort
|
||||||
|
}, function(err, clientSession) {
|
||||||
|
assert( ! err, 'Error should not be negative');
|
||||||
|
|
||||||
|
clientSession.sendSms({
|
||||||
|
'from': 'foo',
|
||||||
|
'to': '46709771337',
|
||||||
|
'message': 'K sKM8NYUuoVbORtCn€swWsvTZjbtYM1TceGJJouolLk4cOtlk7j dxWMI56Domdx2W!dHKjGBR5UsynmUnbp1ysRDCktBri WW2pxIWHv0P7H OVRZNw 6 DBzAqpnd7ZPslwNyi»x OuiNH0R!WM2DTo8ItysNDNe1eNnpLvahhRgv»TC y lvgFrmv4OiUTOP'
|
||||||
|
}, function(err, smsIds, retPduObjs) {
|
||||||
|
assert( ! err, 'Error should not be negative');
|
||||||
|
|
||||||
|
assert(smsIds instanceof Array, 'smsIds should be an Array');
|
||||||
|
assert(smsIds[0] === '2344-1', 'First smsId should be "2344-1"');
|
||||||
|
assert(smsIds[1] === '2344-2', 'Second smsId should be "2344-2"');
|
||||||
|
assert(smsIds[2] === '2344-3', 'Third smsId should be "2344-3"');
|
||||||
|
assert(smsIds[3] === undefined, 'Fourth smsId should be undefined');
|
||||||
|
assert(retPduObjs[0].cmdStatus === 'ESME_ROK', 'Command status should be "ESME_ROK"');
|
||||||
|
assert(retPduObjs[0].cmdName === 'submit_sm_resp', 'Command name should be "submit_sm_resp"');
|
||||||
|
assert(retPduObjs[1].cmdStatus === 'ESME_ROK', 'Command status should be "ESME_ROK"');
|
||||||
|
assert(retPduObjs[1].cmdName === 'submit_sm_resp', 'Command name should be "submit_sm_resp"');
|
||||||
|
assert(retPduObjs[2].cmdStatus === 'ESME_ROK', 'Command status should be "ESME_ROK"');
|
||||||
|
assert(retPduObjs[2].cmdName === 'submit_sm_resp', 'Command name should be "submit_sm_resp"');
|
||||||
|
|
||||||
|
// Gracefully close connection
|
||||||
|
clientSession.unbind();
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should send a long sms and receive dlrs for it', function(done) {
|
it('should send a long sms and receive dlrs for it', function(done) {
|
||||||
portfinder.getPort(function(err, freePort) {
|
portfinder.getPort(function(err, freePort) {
|
||||||
assert( ! err, 'Error should not be negative');
|
assert( ! err, 'Error should not be negative');
|
||||||
|
|||||||
Reference in New Issue
Block a user