diff --git a/lib/session.js b/lib/session.js index a724979..56d28b5 100644 --- a/lib/session.js +++ b/lib/session.js @@ -295,7 +295,7 @@ console.log(retPduObj); if (smsData.smsId !== undefined) { // Todo: Generate random ID - smsData.smsId = 666; + smsData.smsId = '666'; } smsObj.smsId = smsData.smsId; diff --git a/lib/utils.js b/lib/utils.js index a8b0bbc..f1cf7b2 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -3,6 +3,140 @@ var log = require('winston'), defs = require('./defs'); +/** + * Calcualte cmdLength from object + * + * @param obj obj + * @param func callback(err, cmdLength) + */ +function calcCmdLength(obj, callback) { + var cmdLength = 16, // All commands are at least 16 octets long + err, + param, + paramType, + tlvValue, + tlvName, + tlvDef; + + // Handle params - All command params should always exists, even if they do not contain data. + for (param in defs.cmds[obj.cmdName].params) { + + // Get the parameter type, int, string, cstring etc. + // This is needed so we can calculate length etc + paramType = defs.cmds[obj.cmdName].params[param].type; + + if (obj.params[param] === undefined) { + obj.params[param] = paramType.default; + } + + if (isNaN(paramType.size(obj.params[param]))) { + err = new Error('Invalid param value "' + obj.params[param] + '" for param "' + param + '" and command "' + obj.cmdName + '". Is it of the right type?'); + log.error('larvitsmpp: lib/utils.js: calcCmdLength() - ' + err.message); + callback(err); + return; + } + + cmdLength += paramType.size(obj.params[param]); + } + + // TLV params - optional parameters + for (tlvName in obj.tlvs) { + tlvValue = obj.tlvs[tlvName].tagValue; + tlvDef = defs.tlvsById[obj.tlvs[tlvName].tagId]; + + if (tlvDef === undefined) { + tlvDef = defs.tlvs.default; + } + + cmdLength += tlvDef.type.size(tlvValue) + 4; + } + + callback(null, cmdLength); +} + +/** + * Write PDU to buffer + * + * @param obj obj - the PDU object to be written to buffer + * @param int cmdLength - The length of the pdu buffer + * @param func callback(err, buff) + */ +function writeBuffer(obj, cmdLength, callback) { + var offset = 16, // Start the offset on the body + buff, + param, + paramType, + tlvId, + tlvName, + tlvValue, + tlvDef, + tlvSize, + err; + + if (isNaN(cmdLength) || cmdLength < 16) { + if (isNaN(cmdLength)) { + err = new Error('cmdLength is NaN'); + } + + if (cmdLength < 16) { + err = new Error('cmdLength is less than 16 (' + cmdLength + ')'); + } + + log.error('larvitsmpp: lib/utils.js: objToPdu() - writeBuffer() - ' + err.message); + callback(err); + return; + } + + buff = new Buffer(cmdLength); + + // Write PDU header + try { + buff.writeUInt32BE(cmdLength, 0); // Command length for the first 4 octets + buff.writeUInt32BE(defs.cmds[obj.cmdName].id, 4); // Command id for the second 4 octets + buff.writeUInt32BE(defs.errors[obj.cmdStatus], 8); // Command status for the third 4 octets + buff.writeUInt32BE(obj.seqNr, 12); // Sequence number as the fourth 4 octets + } catch (e) { + err = new Error('Could not write PDU header, catched err: ' + e.message, obj); + log.error('larvitsmpp: lib/utils.js: writeBuffer() - ' + err.message); + callback(err); + return; + } + + // Cycle through the defs list to make sure the params are in the right order + for (param in defs.cmds[obj.cmdName].params) { + paramType = defs.cmds[obj.cmdName].params[param].type; + + // Write parameter value to buffer using the types method write() + paramType.write(obj.params[param], buff, offset); + + // Increase the offset for the next param + offset += paramType.size(obj.params[param]); + } + + // Cycle through the tlvs + for (tlvName in obj.tlvs) { + tlvId = obj.tlvs[tlvName].tagId; + tlvValue = obj.tlvs[tlvName].tagValue; + tlvDef = defs.tlvsById[tlvId]; + + if (tlvDef === undefined) { + tlvDef = defs.tlvs.default; + } + + tlvSize = tlvDef.type.size(tlvValue); + + log.silly('larvitsmpp: lib/utils.js: objToPdu() - writeBuffer() - Writing TLV "' + tlvName + '" offset: ' + offset + ' value: "' + tlvValue + '"'); + + buff.writeUInt16BE(tlvId, offset); + buff.writeUInt16BE(tlvSize, offset + 2); + tlvDef.type.write(tlvValue, buff, offset + 4); + + offset += tlvDef.type.size(tlvValue) + 4; + } + + callback(null, buff); +} + /** * Decode a short_message * @@ -175,100 +309,9 @@ function pduToObj(pdu, callback) { * @param func callback(err, pdu) */ function objToPdu(obj, callback) { - var cmdLength = 16, // All commands are at least 16 octets long - err = null, + var err = null, shortMsg, - param, - paramType, - buff, - seqNr, - tlvId, - tlvName, - tlvValue, - tlvDef, - tlvSize; - - function calcCmdLength() { - // Handle params - All command params should always exists, even if they do not contain data. - for (param in defs.cmds[obj.cmdName].params) { - - // Get the parameter type, int, string, cstring etc. - // This is needed so we can calculate length etc - paramType = defs.cmds[obj.cmdName].params[param].type; - - if (obj.params[param] === undefined) { - obj.params[param] = paramType.default; - } - - cmdLength += paramType.size(obj.params[param]); - } - - // TLV params - optional parameters - for (tlvName in obj.tlvs) { - tlvValue = obj.tlvs[tlvName].tagValue; - tlvDef = defs.tlvsById[obj.tlvs[tlvName].tagId]; - - if (tlvDef === undefined) { - tlvDef = defs.tlvs.default; - } - - cmdLength += tlvDef.type.size(tlvValue) + 4; - } - } - - // Used to write buffer once the command length is known - function writeBuffer() { - var offset = 16, // Start the offset on the body - err; - - - buff = new Buffer(cmdLength); - - // Write PDU header - try { - buff.writeUInt32BE(cmdLength, 0); // Command length for the first 4 octets - buff.writeUInt32BE(defs.cmds[obj.cmdName].id, 4); // Command id for the second 4 octets - buff.writeUInt32BE(defs.errors[obj.cmdStatus], 8); // Command status for the third 4 octets - buff.writeUInt32BE(seqNr, 12); // Sequence number as the fourth 4 octets - } catch (e) { - err = new Error('Could not write PDU header, catched err: ' + e.message, obj); - log.error('larvitsmpp: lib/utils.js: objToPdu() - writeBuffer() - ' + err.message); - callback(err); - return; - } - - // Cycle through the defs list to make sure the params are in the right order - for (param in defs.cmds[obj.cmdName].params) { - paramType = defs.cmds[obj.cmdName].params[param].type; - - // Write parameter value to buffer using the types method write() - paramType.write(obj.params[param], buff, offset); - - // Increase the offset for the next param - offset += paramType.size(obj.params[param]); - } - - // Cycle through the tlvs - for (tlvName in obj.tlvs) { - tlvId = obj.tlvs[tlvName].tagId; - tlvValue = obj.tlvs[tlvName].tagValue; - tlvDef = defs.tlvsById[tlvId]; - - if (tlvDef === undefined) { - tlvDef = defs.tlvs.default; - } - - tlvSize = tlvDef.type.size(tlvValue); - - log.silly('larvitsmpp: lib/utils.js: objToPdu() - writeBuffer() - Writing TLV "' + tlvName + '" offset: ' + offset + ' value: "' + tlvValue + '"'); - - buff.writeUInt16BE(tlvId, offset); - buff.writeUInt16BE(tlvSize, offset + 2); - tlvDef.type.write(tlvValue, buff, offset + 4); - - offset += tlvDef.type.size(tlvValue) + 4; - } - } + seqNr; // Check so the command is ok if (defs.cmds[obj.cmdName] === undefined) { @@ -322,11 +365,16 @@ function objToPdu(obj, callback) { log.silly('larvitsmpp: lib/utils.js: objToPdu() - encoding message "' + shortMsg + '" to "' + obj.params.short_message.toString('hex') + '"'); } - calcCmdLength(); - writeBuffer(); - if (buff) { - callback(null, buff); - } + calcCmdLength(obj, function(err, cmdLength) { + if (err) { + callback(err); + return; + } + + writeBuffer(obj, cmdLength, function(err, buff) { + callback(err, buff); + }); + }); } /**