Important fixes to short_message

This commit is contained in:
2015-04-06 22:47:45 +02:00
parent 022a12e181
commit bca6b67342
3 changed files with 94 additions and 52 deletions
+6 -16
View File
@@ -192,30 +192,20 @@ types = {
default: '' default: ''
}, },
buffer: { buffer: {
read: function(buffer, offset) { read: function(buffer, offset, length) {
var length = buffer.readUInt8(offset ++);
return buffer.slice(offset, offset + length); return buffer.slice(offset, offset + length);
}, },
write: function(value, buffer, offset) { write: function(value, buffer, offset) {
buffer.writeUInt8(value.length, offset ++);
if (typeof value === 'string') { if (typeof value === 'string') {
value = new Buffer(value, 'ascii'); value = new Buffer(value, 'ascii');
} }
value.copy(buffer, offset); value.copy(buffer, offset);
}, },
size: function(buffer, offset) { size: function(buffer) {
var length; if (buffer[buffer.length - 1] === 0x00) {
return buffer.length - 1;
if (isNaN(offset)) {
offset = 0;
}
length = buffer.readUInt8(offset ++);
if (buffer[offset + length + 1] !== undefined && buffer.slice(offset + length + 1).toString('hex') === '00') {
return offset + length + 1;
} else { } else {
return offset + length; return buffer.length;
} }
}, },
default: new Buffer(0) default: new Buffer(0)
@@ -1325,7 +1315,7 @@ cmds = {
replace_if_present_flag: {type: types.int8}, replace_if_present_flag: {type: types.int8},
data_coding: {type: types.int8}, data_coding: {type: types.int8},
sm_default_msg_id: {type: types.int8}, sm_default_msg_id: {type: types.int8},
//sm_length: {type: types.int8}, sm_length: {type: types.int8},
short_message: {type: types.buffer, filter: filters.message} short_message: {type: types.buffer, filter: filters.message}
} }
}, },
+67 -34
View File
@@ -11,11 +11,10 @@ var log = require('winston'),
* *
* @param buf buffer * @param buf buffer
* @param str encoding 'ASCII', 'LATIN1' or 'UCS2' or hex values * @param str encoding 'ASCII', 'LATIN1' or 'UCS2' or hex values
* @param func callback(err, str) - str will be in utf8 format * @return str in utf8 format
*/ */
function decodeMsg(buffer, encoding, callback) { function decodeMsg(buffer, encoding) {
var err = null, var checkEnc;
checkEnc;
for (checkEnc in defs.consts.ENCODING) { for (checkEnc in defs.consts.ENCODING) {
if (parseInt(encoding) === defs.consts.ENCODING[checkEnc] || encoding === checkEnc) { if (parseInt(encoding) === defs.consts.ENCODING[checkEnc] || encoding === checkEnc) {
@@ -28,18 +27,14 @@ function decodeMsg(buffer, encoding, callback) {
encoding = 'ASCII'; encoding = 'ASCII';
} }
callback(err, defs.encodings[encoding].decode(buffer)); return defs.encodings[encoding].decode(buffer);
} }
/*
function encodeMsg(str, callback) {
var encoding = defs.encodings.detect(str),
err = null,
buff;
buff = defs.encodings[encoding].encode(str); function encodeMsg(str) {
var encoding = defs.encodings.detect(str);
callback(err, buff); return defs.encodings[encoding].encode(str);
}*/ }
/** /**
* Transforms a PDU to an object * Transforms a PDU to an object
@@ -104,17 +99,22 @@ function pduToObj(pdu, callback) {
// Get the parameter value by using the definition type read() function // Get the parameter value by using the definition type read() function
try { try {
retObj.params[param] = command.params[param].type.read(pdu, offset); retObj.params[param] = command.params[param].type.read(pdu, offset, retObj.params.sm_length);
// Short message seems to sometimes be terminated with a NULL and sometimes not. Very ugly and needs special care.
if (param === 'short_message') {
paramSize = command.params[param].type.size(pdu, offset);
} else {
paramSize = command.params[param].type.size(retObj.params[param]); paramSize = command.params[param].type.size(retObj.params[param]);
}
log.silly('larvitsmpp: pduToObj() - Reading param "' + param + '" at offset ' + offset + ' with calculated size: ' + paramSize + ' content in hex: ' + pdu.slice(offset, offset + paramSize).toString('hex')); log.silly('larvitsmpp: pduToObj() - Reading param "' + param + '" at offset ' + offset + ' with calculated size: ' + paramSize + ' content in hex: ' + pdu.slice(offset, offset + paramSize).toString('hex'));
if (param === 'short_message') {
// 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.
if (pdu.slice(offset + retObj.params.sm_length, offset + retObj.params.sm_length + 1).toString('hex') === '00') {
log.silly('larvitsmpp: pduToObj() - short_message is followed by a NULL octet, increase paramSize one extra to account for that');
paramSize ++;
}
}
// Increase the offset by the current params length // Increase the offset by the current params length
offset += paramSize; offset += paramSize;
} catch (e) { } catch (e) {
@@ -145,17 +145,9 @@ function pduToObj(pdu, callback) {
// 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);
decodeMsg(retObj.params.short_message, retObj.params.data_coding, function(err, decodedMsg) {
if (err) {
callback(err);
return;
}
retObj.params.short_message = decodedMsg;
callback(null, retObj); callback(null, retObj);
});
} else { } else {
// We need to do the standard callback in an else statement since // We need to do the standard callback in an else statement since
// this always would be called before the above callback if we didn't // this always would be called before the above callback if we didn't
@@ -172,6 +164,7 @@ function pduToObj(pdu, callback) {
function objToPdu(obj, callback) { function objToPdu(obj, callback) {
var cmdLength = 16, // All commands are at least 16 octets long var cmdLength = 16, // All commands are at least 16 octets long
err = null, err = null,
shortMsg,
param, param,
paramType, paramType,
buff, buff,
@@ -232,6 +225,28 @@ function objToPdu(obj, callback) {
return; return;
} }
// All params are mandatory. Set them if they are not set
if (obj.params === undefined) {
obj.params = {};
}
// If param "short_message" exists, encode it and set parameter "data_coding" accordingly
if (obj.params.short_message !== undefined && ! Buffer.isBuffer(obj.params.short_message)) {
// Detect encoding
obj.params.data_coding = defs.encodings.detect(obj.params.short_message);
log.silly('larvitsmpp: objToPdu() - data_coding "' + obj.params.data_coding + '" detected');
// Now set the hex value
obj.params.data_coding = defs.consts.ENCODING[obj.params.data_coding];
// Acutally encode the string
shortMsg = obj.params.short_message;
obj.params.short_message = encodeMsg(obj.params.short_message);
obj.params.sm_length = obj.params.short_message.length;
log.silly('larvitsmpp: objToPdu() - encoding message "' + shortMsg + '" to "' + obj.params.short_message.toString('hex') + '"');
}
// Handle params - All command params should always exists, even if they do not contain data. // Handle params - All command params should always exists, even if they do not contain data.
for (param in defs.cmds[obj.cmdName].params) { for (param in defs.cmds[obj.cmdName].params) {
@@ -239,11 +254,6 @@ function objToPdu(obj, callback) {
// This is needed so we can calculate length etc // This is needed so we can calculate length etc
paramType = defs.cmds[obj.cmdName].params[param].type; paramType = defs.cmds[obj.cmdName].params[param].type;
// All params are mandatory. Set them if they are not set
if (obj.params === undefined) {
obj.params = {};
}
if (obj.params[param] === undefined) { if (obj.params[param] === undefined) {
obj.params[param] = paramType.default; obj.params[param] = paramType.default;
} }
@@ -521,6 +531,29 @@ function session(sock) {
}); });
}; };
/**
* Send an SMS
*
* @param obj smsOptions
* from - alphanum or international format
* to - international format
* message - string
* dlr - boolean defaults to false
* @param func callback(err, retPduObj)
*/
sessionEmitter.sendSms = function(smsOptions, callback) {
var pduObj = {};
pduObj.cmdName = 'submti_sm';
pduObj.params = {
'source_addr': smsOptions.from,
'destination_addr': smsOptions.to,
'short_message': smsOptions.message
};
sessionEmitter.send(pduObj, callback);
};
sessionEmitter.deliverSm = function(pduObj) { sessionEmitter.deliverSm = function(pduObj) {
console.log(pduObj); console.log(pduObj);
sessionEmitter.sendReturn(pduObj); sessionEmitter.sendReturn(pduObj);
+19
View File
@@ -117,6 +117,25 @@ describe('PDU convertion', function() {
done(); done();
}); });
}); });
it('should create a very simple submit_sm PDU', function(done) {
larvitsmpp.objToPdu({
'cmdName': 'submit_sm',
'cmdStatus': 'ESME_ROK',
'seqNr': 12,
'params': {
'source_addr': '46701113311',
'destination_addr': '46709771337',
'short_message': 'Hello world'
}
}, function(err, pdu) {
assert( ! err, 'Error should be negative');
assert(pdu.toString('hex') === '0000004200000004000000000000000c00000034363730313131333331310000003436373039373731333337000000000000000001000b48656c6c6f20776f726c64');
done();
});
});
}); });
}); });