diff --git a/defs.js b/defs.js index 850f818..11e085f 100644 --- a/defs.js +++ b/defs.js @@ -767,6 +767,10 @@ filters.callback_num_atag = { }; tlvs = { + default: { + id: undefined, + type: types.tlv.buffer + }, dest_addr_subunit: { id: 0x0005, type: types.tlv.int8 diff --git a/larvitsmpp.js b/larvitsmpp.js index 21abc8f..bbfd1ee 100644 --- a/larvitsmpp.js +++ b/larvitsmpp.js @@ -185,7 +185,39 @@ function objToPdu(obj, callback) { paramType, buff, seqNr, - i; + 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() { @@ -209,6 +241,27 @@ function objToPdu(obj, callback) { // 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: 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; + } } // Check so the command is ok @@ -263,31 +316,7 @@ function objToPdu(obj, callback) { 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. - 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]); - } - - if (obj.params !== undefined) { - i = 0; - while (obj.params[i] !== undefined) { - - - i ++; - } - } - - // TLV params - optional parameters - + calcCmdLength(); writeBuffer(); callback(null, buff); } @@ -296,10 +325,11 @@ function objToPdu(obj, callback) { * Create a PDU as a return to another PDU * * @param obj or buf pdu - * @param str status - see list at defs.errors - defaults to 'ESME_ROK' - no error - * @param func callback(err, pduBuffer) + * @param str status - see list at defs.errors - defaults to 'ESME_ROK' - no error (OPTIONAL) + * @param obj tlvs (OPTIONAL) + * @param func callback(err, pduBuffer) (OPTIONAL) */ -function pduReturn(pdu, status, callback) { +function pduReturn(pdu, status, tlvs, callback) { var err = null, retPdu = {}, param; @@ -325,6 +355,12 @@ function pduReturn(pdu, status, callback) { if (typeof status === 'function') { callback = status; status = 'ESME_ROK'; + tlvs = undefined; + } + + if (typeof tlvs === 'function') { + callback = tlvs; + tlvs = undefined; } if (status === undefined) { @@ -353,6 +389,7 @@ function pduReturn(pdu, status, callback) { retPdu.cmdStatus = status; retPdu.seqNr = pdu.seqNr; retPdu.params = {}; + retPdu.tlvs = tlvs; // Populate parameters that should exist in the response for (param in defs.cmds[pdu.cmdName + '_resp'].params) { @@ -517,9 +554,9 @@ function session(sock) { * Send a return to given PDU * * @param obj or buf pdu - * @param str status - see list at defs.errors - defaults to 'ESME_ROK' - no error + * @param str status - see list at defs.errors - defaults to 'ESME_ROK' - no error (OPTIONAL) * @param bol closeAfterSend - if true will close the socket after sending (OPTIONAL) - * @param func callback(err) + * @param func callback(err) (OPTIONAL) */ returnObj.sendReturn = function(pdu, status, closeAfterSend, callback) { if (typeof closeAfterSend === 'function') { @@ -617,15 +654,33 @@ function session(sock) { returnObj.sendReturn(pduObj); }; + // Handle incoming submit_sm returnObj.submitSm = function(pduObj) { - returnObj.emit('sms', { + var smsObj = {}; + + smsObj = { 'from': pduObj.params.source_addr, 'to': pduObj.params.destination_addr, 'message': pduObj.params.short_message, - 'dlrRequested': Boolean(pduObj.params.registered_delivery), - 'smsId': pduObj.params.message_id - }, pduObj); - returnObj.sendReturn(pduObj); + 'dlrRequested': Boolean(pduObj.params.registered_delivery) + }; + + function smsReceived(smsData) { + if (smsData === undefined) { + smsData = {}; + } + + if (smsData.smsId !== undefined) { + // Todo: Generate random ID + smsData.smsId = 666; + } + + smsObj.smsId = smsData.smsId; + + returnObj.sendReturn(pduObj, {'message_id': smsObj.smsId}); + } + + returnObj.emit('sms', smsObj, smsReceived); }; // Dummy, should be extended by serverSession or clientSession diff --git a/test/03_pdu.js b/test/03_pdu.js index 186e3b2..89dca88 100644 --- a/test/03_pdu.js +++ b/test/03_pdu.js @@ -158,6 +158,44 @@ describe('PDU convertion', function() { done(); }); + }); + + it('should add TLVs to a PDU', function(done) { + var pduObj = { + 'cmdName': 'deliver_sm', + 'seqNr': 393, + 'cmdStatus': 'ESME_ROK', + 'params': { + 'source_addr': '46701113311', + 'destination_addr': '46709771337', + 'esm_class': 4, + 'short_message': 'random stuff' + }, + 'tlvs': { + 'receipted_message_id': { + 'tagId': 0x001E, + 'tagName': 'receipted_message_id', + 'tagValue': '293f293' + }, + '5142': { + 'tagId': 5142, + 'tagName': 'Nils', + 'tagValue': new Buffer('blajfoo', 'ascii') + } + } + }; + + larvitsmpp.objToPdu(pduObj, function(err, pduBuf) { + assert( ! err, 'Error should be negative'); + + larvitsmpp.pduToObj(pduBuf, function(err, pduObj2) { + assert( ! err, 'Error should be negative'); + + console.log(pduObj2); + + done(); + }); + }); }); });