Fixed issue with TLV starting with a NULL byte that follows directly upon a short_message

This commit is contained in:
2015-05-03 18:33:02 +02:00
parent 6fa1bd319f
commit e361ff775f
4 changed files with 70 additions and 9 deletions
+1 -1
View File
@@ -117,7 +117,7 @@ Example code below:
}); });
// Oh, the sms sender wants a dlr (delivery report), send it! // Oh, the sms sender wants a dlr (delivery report), send it!
if (sms.dlrRequested === true) { if (sms.dlr === true) {
serverSession.sendDlr(sms); serverSession.sendDlr(sms);
// To send a negative delivery report do: // To send a negative delivery report do:
+3 -3
View File
@@ -207,7 +207,7 @@ function session(sock) {
* from - alphanum or international format * from - alphanum or international format
* to - international format * to - international format
* message - string * message - string
* dlrRequested - boolean defaults to false * dlr - boolean defaults to false
* @param func callback(err, smsId, retPduObj) * @param func callback(err, smsId, retPduObj)
*/ */
returnObj.sendSms = function(smsOptions, callback) { returnObj.sendSms = function(smsOptions, callback) {
@@ -221,7 +221,7 @@ function session(sock) {
}; };
// Request DLRs! // Request DLRs!
if (smsOptions.dlrRequested) { if (smsOptions.dlr) {
pduObj.params.registered_delivery = 0x01; pduObj.params.registered_delivery = 0x01;
} }
@@ -374,7 +374,7 @@ function session(sock) {
'to': pduObj.params.destination_addr, 'to': pduObj.params.destination_addr,
'submitTime': new Date(), 'submitTime': new Date(),
'message': pduObj.params.short_message, 'message': pduObj.params.short_message,
'dlrRequested': Boolean(pduObj.params.registered_delivery) 'dlr': Boolean(pduObj.params.registered_delivery)
}; };
function smsReceived(smsData) { function smsReceived(smsData) {
+23 -5
View File
@@ -180,9 +180,10 @@ function encodeMsg(str) {
* Transforms a PDU to an object * Transforms a PDU to an object
* *
* @param buf pdu * @param buf pdu
* @param bol stupidNullByte - Define if the short_message should be followed by a stupid NULL byte - will be auto resolved if left undefined
* @param func callback(err, obj) * @param func callback(err, obj)
*/ */
function pduToObj(pdu, callback) { function pduToObj(pdu, stupidNullByte, callback) {
var retObj = {'params': {}, 'tlvs': {}}, var retObj = {'params': {}, 'tlvs': {}},
err = null, err = null,
offset, offset,
@@ -193,6 +194,11 @@ function pduToObj(pdu, callback) {
tlvValue, tlvValue,
paramSize; paramSize;
if (typeof stupidNullByte === 'function') {
callback = stupidNullByte;
stupidNullByte = undefined;
}
// Returns true if this PDU is a response to another PDU // Returns true if this PDU is a response to another PDU
retObj.isResponse = function() { retObj.isResponse = function() {
return ! ! (this.cmdId & 0x80000000); return ! ! (this.cmdId & 0x80000000);
@@ -250,9 +256,8 @@ function pduToObj(pdu, callback) {
// Check if we have a trailing NULL octet after the short_message. Some idiot thought that would be a good idea // Check if we have a trailing NULL octet after the short_message. Some idiot thought that would be a good idea
// in some implementations, so we need to account for that. // in some implementations, so we need to account for that.
if (pdu.slice(offset + retObj.params.sm_length, offset + retObj.params.sm_length + 1).toString('hex') === '00') { if (stupidNullByte === true) {
log.silly('larvitsmpp: lib/utils.js: pduToObj() - short_message is followed by a NULL octet, increase paramSize one extra to account for that'); log.silly('larvitsmpp: lib/utils.js: pduToObj() - stupidNullByte is set, so short_message is followed by a NULL octet, increase paramSize one extra to account for that');
paramSize ++; paramSize ++;
} }
} }
@@ -269,7 +274,8 @@ function pduToObj(pdu, callback) {
} }
// If the length is greater than the current offset, there must be TLVs - resolve them! // If the length is greater than the current offset, there must be TLVs - resolve them!
while (offset < retObj.cmdLength) { // The minimal size for a TLV is its head, 4 octets
while ((offset + 4) < retObj.cmdLength) {
try { try {
tlvCmdId = pdu.readInt16BE(offset); tlvCmdId = pdu.readInt16BE(offset);
tlvLength = pdu.readInt16BE(offset + 2); tlvLength = pdu.readInt16BE(offset + 2);
@@ -277,6 +283,7 @@ function pduToObj(pdu, callback) {
err = new Error('Unable to read TLV at offset "' + offset + '", given cmdLength: "' + retObj.cmdLength + '" pdu: ' + pdu.toString('hex')); err = new Error('Unable to read TLV at offset "' + offset + '", given cmdLength: "' + retObj.cmdLength + '" pdu: ' + pdu.toString('hex'));
log.error('larvitsmpp: lib/utils.js: pduToObj() - ' + err.message); log.error('larvitsmpp: lib/utils.js: pduToObj() - ' + err.message);
callback(err); callback(err);
return;
} }
if (defs.tlvsById[tlvCmdId] === undefined) { if (defs.tlvsById[tlvCmdId] === undefined) {
@@ -308,6 +315,17 @@ function pduToObj(pdu, callback) {
offset = offset + 4 + tlvLength; offset = offset + 4 + tlvLength;
} }
if (offset !== retObj.cmdLength && stupidNullByte === undefined) {
log.verbose('larvitsmpp: lib/utils.js: pduToObj() - Offset (' + offset + ') !== cmdLength (' + retObj.cmdLength + ') for seqNr: ' + retObj.seqNr + ' - retry with the stupid NULL byte for short_message');
pduToObj(pdu, true, callback);
return;
}
if (offset !== retObj.cmdLength) {
log.warn('larvitsmpp: lib/utils.js: pduToObj() - Offset (' + offset + ') !== cmdLength (' + retObj.cmdLength + ') for seqNr: ' + retObj.seqNr);
}
// Decode the short message if it is set // Decode the short message if it is set
if (retObj.params.short_message !== undefined) { if (retObj.params.short_message !== undefined) {
retObj.params.short_message = decodeMsg(retObj.params.short_message, retObj.params.data_coding); retObj.params.short_message = decodeMsg(retObj.params.short_message, retObj.params.data_coding);
+43
View File
@@ -224,6 +224,49 @@ describe('PDU convertion', function() {
}); });
}); });
}); });
it('should add some other TLVs to a PDU', function(done) {
var pduObj = {
'cmdName': 'deliver_sm',
'params': {
'source_addr': '46701113311',
'destination_addr': '46709771337',
'esm_class': 4,
'short_message': 'id:450 sub:001 dlvrd:1 submit date:1504031342 done date:1504031342 stat:DELIVRD err:0 text:xxx'
},
'tlvs': {
'receipted_message_id': {
'tagId': 30,
'tagName': 'receipted_message_id',
'tagValue': 450
},
'message_state': {
'tagId': 1063,
'tagName': 'message_state',
'tagValue': 2
}
},
'seqNr': 323
};
larvitsmpp.utils.objToPdu(pduObj, function(err, pduBuf) {
assert( ! err, 'Error should be negative');
larvitsmpp.utils.pduToObj(pduBuf, function(err, retPduObj) {
assert( ! err, 'Error should be negative');
assert(retPduObj.params.short_message === 'id:450 sub:001 dlvrd:1 submit date:1504031342 done date:1504031342 stat:DELIVRD err:0 text:xxx', 'short_message should be preserved');
assert(retPduObj.cmdName === 'deliver_sm', 'Command name should be "deliver_sm"');
assert(retPduObj.tlvs.message_state !== undefined, 'TLV message_state should be set');
assert(retPduObj.tlvs.message_state.tagValue === 2, 'TLV message_state tagValue should be 2');
assert(retPduObj.tlvs.receipted_message_id !== undefined, 'TLV receipted_message_id should be set');
assert(retPduObj.tlvs.receipted_message_id.tagValue === '450', 'TLV receipted_message_id tagValue should be "450"');
assert(retPduObj.seqNr === 323, 'Sequence number should be 323');
done();
});
});
});
}); });
describe('Return PDUs', function() { describe('Return PDUs', function() {