Important fixes to short_message
This commit is contained in:
@@ -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}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+69
-36
@@ -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);
|
||||||
|
paramSize = command.params[param].type.size(retObj.params[param]);
|
||||||
// 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]);
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
callback(null, retObj);
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
retObj.params.short_message = decodedMsg;
|
|
||||||
|
|
||||||
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);
|
||||||
|
|||||||
@@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user