Monstrous amount of changes. Bad commit disciplin.

This commit is contained in:
2015-05-10 23:42:11 +02:00
parent 2307800d22
commit 80c0153b57
4 changed files with 292 additions and 107 deletions
+272 -96
View File
@@ -2,8 +2,167 @@
var log = require('winston'),
events = require('events'),
moment = require('moment'),
utils = require('./utils'),
defs = require('./defs');
defs = require('./defs'),
async = require('async');
/*
* Send a response to an sms
* This must be called from an sms object context
*
* @param str status - see list at defs.errors - defaults to 'ESME_ROK' - no error (OPTIONAL)
* @param func callback(err, [retPdu, ...])
*/
function smsResp(status, callback) {
var sms = this,
err,
i,
tasks = [];
if (typeof status === 'function') {
callback = status;
status = true;
}
if (typeof callback !== 'function') {
callback = function() {};
}
if (sms.smsId === undefined) {
sms.smsId = '';
}
// Accept a generic positive status
if (status === 'true' || status === true || status === 0) {
status = 'ESME_ROK';
}
// Accept a generic negative status
if (status === 'false' || status === false || status === 1) {
status = 'ESME_RUNKNOWNERR'; // Set to unknown error in this case
}
if (sms.pduObjs === undefined && sms.pduObj === undefined) {
err = new Error('No pdu objects found to base return PDU upon');
log.warn('larvitsmpp: lib/session.js: smsResp() - ' + err.message);
callback(err);
return;
}
if (sms.pduObjs === undefined) {
sms.pduObjs = [sms.pduObjs];
}
// Build async tasks to run the responses in parallel
i = 0;
while (sms.pduObjs[i] !== undefined) {
tasks.push(function(callback) {
sms.session.sendReturn(
sms.pduObj,
status,
{'message_id': sms.smsId},
false,
callback
);
});
i ++;
}
sms.session.sendReturn(
sms.pduObj,
status,
{'message_id': sms.smsId},
false,
callback
);
}
/**
* Send a dlr to an sms
* This must be called from an sms object context
*
* @param str status - see list at defs.consts.MESSAGE_STATE - defaults to 'DELIVERED'
* @param func callback(err, retPdu)
*/
function smsDlr(status, callback) {
var shortMessage,
dlrPduObj,
err,
sms = this;
if (typeof status === 'function') {
callback = status;
status = undefined;
}
if (status === undefined || status === true || status === 2 || status === 'true') {
status = 2;
} else if (defs.consts.MESSAGE_STATE[status] !== undefined) {
status = defs.consts.MESSAGE_STATE[status];
} else if (defs.constsById.MESSAGE_STATE[status]) {
status = parseInt(status);
} else {
status = 5; // UNDELIVERABLE
}
if (typeof callback !== 'function') {
callback = function() {};
}
if (sms.smsId === undefined) {
err = new Error('Trying to send DLR with no smsId.');
log.warn('larvitsmpp: lib/session.js: smsDlr() - ' + err.message);
callback(err);
return;
}
shortMessage = 'id:' + sms.smsId + ' sub:001 ';
if (status === 2) {
shortMessage += 'dlvrd:1 ';
} else {
shortMessage += 'dlvrd:0 ';
}
shortMessage += 'submit date:' + utils.smppDate(sms.submitTime);
shortMessage += ' done date:' + utils.smppDate(new Date());
if (status === 2) {
shortMessage += ' stat:DELIVRD err:0 text:xxx';
} else {
shortMessage += ' stat:UNDELIVERABLE err:1 text:xxx';
}
dlrPduObj = {
'cmdName': 'deliver_sm',
'params': {
'source_addr': sms.from,
'destination_addr': sms.to,
'esm_class': 4,
'short_message': shortMessage
},
'tlvs': {
'receipted_message_id': {
'tagId': 0x001E,
'tagName': 'receipted_message_id',
'tagValue': sms.smsId
},
'message_state': {
'tagId': 0x0427,
'tagName': 'message_state',
'tagValue': status
}
}
};
sms.session.send(dlrPduObj, false, callback);
}
/**
* Generic session function
@@ -136,14 +295,14 @@ function session(sock) {
log.debug('larvitsmpp: lib/session.js: session() - returnObj.send() - returnObj.on(incomingPduObj) - cmdName: ' + incPduObj.cmdName + ' seqNr: ' + incPduObj.seqNr + ' cmdStatus: ' + incPduObj.cmdStatus);
// Make sure this is the actual response to the sent PDU
if (incPduObj.isResponse() && incPduObj.seqNr === pduObj.seqNr) {
if (incPduObj.isResp() && incPduObj.seqNr === pduObj.seqNr) {
callback(null, incPduObj);
if (closeAfterSend) {
returnObj.closeSocket();
}
} else {
err = new Error('larvitsmpp: lib/session.js: session() - returnObj.send() - returnObj.on(incomingPduObj) - Event triggered but incoming PDU is not a response or seqNr does not match. isResponse: ' + incPduObj.isResponse().toString() + ' incSeqNr: ' + incPduObj.seqNr + ' expected seqNr: ' + pduObj.seqNr);
err = new Error('larvitsmpp: lib/session.js: session() - returnObj.send() - returnObj.on(incomingPduObj) - Event triggered but incoming PDU is not a response or seqNr does not match. isResp: ' + incPduObj.isResp().toString() + ' incSeqNr: ' + incPduObj.seqNr + ' expected seqNr: ' + pduObj.seqNr);
log.warn(err.message);
callback(err);
}
@@ -189,6 +348,8 @@ function session(sock) {
return;
}
log.silly('larvitsmpp: lib/session.js: session() - returnObj.sendReturn() - Sending return PDU: ' + retPdu.toString('hex'));
returnObj.sockWrite(retPdu, closeAfterSend);
if (typeof callback === 'function') {
@@ -208,7 +369,8 @@ function session(sock) {
* @param func callback(err, smsId, retPduObj)
*/
returnObj.sendLongSms = function(smsOptions, callback) {
var msgs = utils.splitMsg(smsOptions.message),
var smsIds = [],
msgs = utils.splitMsg(smsOptions.message),
encoding = defs.encodings.detect(smsOptions.message); // Set encoding once for all message parts
function sendPart(i) {
@@ -233,8 +395,10 @@ function session(sock) {
log.debug('larvitsmpp: lib/session.js: returnObj.sendLongSms() - pduObj: ' + JSON.stringify(pduObj));
returnObj.send(pduObj, function(err, retPduObj) {
smsIds.push(retPduObj.params.message_id);
if (typeof callback === 'function' && msgs[i + 1] === undefined) {
callback(err, retPduObj.params.message_id, retPduObj);
callback(err, smsIds, retPduObj);
} else if (msgs[i + 1] !== undefined) {
sendPart(i + 1);
}
@@ -281,97 +445,106 @@ function session(sock) {
returnObj.send(pduObj, function(err, retPduObj) {
if (typeof callback === 'function') {
callback(err, retPduObj.params.message_id, retPduObj);
callback(err, [retPduObj.params.message_id], retPduObj);
}
});
};
/**
* Send a DLR
*
* @param obj sms - sms object
* @param bol status - defaults to true
* @param func callback(err)
*/
returnObj.sendDlr = function(sms, status, callback) {
var shortMessage = 'id:' + sms.smsId + ' sub:001 ',
dlrPduObj;
// Temporary storage for long sms parts
// These should be cleared if they lingre to long to avoid memory leaks
returnObj.longSmses = {};
if (typeof status === 'function') {
callback = status;
status = true;
}
// Store long smses in the temporary storage
returnObj.longSms = function(pduObj) {
var smsGroupId = pduObj.params.short_message[3],
smsParts = pduObj.params.short_message[4],
longSmsId = pduObj.params.source_addr + '_' + pduObj.params.destination_addr + '_' + smsGroupId;
if (status === undefined) {
status = true;
}
if (status) {
shortMessage += 'dlvrd:1 ';
if (returnObj.longSmses[longSmsId] === undefined) {
returnObj.longSmses[longSmsId] = {
'created': new Date(),
'partsCount': parseInt(smsParts),
'pduObjs': [{
'partNr': pduObj.params.short_message[5], // We save this here to easier sort the array later on
'pduObj': pduObj
}]
};
} else {
shortMessage += 'dlvrd:0 ';
returnObj.longSmses[longSmsId].pduObjs.push(pduObj);
}
};
shortMessage += 'submit date:' + utils.smppDate(sms.submitTime);
shortMessage += ' done date:' + utils.smppDate(new Date());
// Walk through the long sms storage to investigate if we can send complete messages along
// or should remove old ones
returnObj.checkLongSmses = function() {
var smsGroupId,
smsGroup,
smsObj,
i,
curPduObj;
if (status) {
shortMessage += ' stat:DELIVRD err:0 text:xxx';
} else {
shortMessage += ' stat:UNDELIVERABLE err:1 text:xxx';
}
dlrPduObj = {
'cmdName': 'deliver_sm',
'params': {
'source_addr': sms.from,
'destination_addr': sms.to,
'esm_class': 4,
'short_message': shortMessage
},
'tlvs': {
'receipted_message_id': {
'tagId': 0x001E,
'tagName': 'receipted_message_id',
'tagValue': sms.smsId
},
'message_state': {
'tagId': 0x0427,
'tagName': 'message_state',
'tagValue': 2
}
}
};
if ( ! status) {
dlrPduObj.tlvs.message_state.tagValue = 5;
}
dlrPduObj.seqNr = 323;
utils.objToPdu(dlrPduObj, function(err, pdu) {
if (err) {
throw err;
// Sort function to sort group parts
function sortLongSmsPdus(a, b) {
if (a.partNr < b.partNr) {
return - 1;
}
utils.pduToObj(pdu, function(err, newObj) {
if (err) {
throw err;
if (a.partNr > b.partNr) {
return 1;
}
return 0;
}
// Callback function for emitted sms event
function smsReceived(smsData) {
delete returnObj.longSmses[smsGroupId];
}
for (smsGroupId in returnObj.longSmses) {
smsGroup = returnObj.longSmses[smsGroupId];
// All parts are accounted for! Emit sms event and clear from tmp storage
if (smsGroup.partsCount === smsGroup.pduObjs.length) {
log.debug('larvitsmpp: lib/session.js: session() - returnObj.checkLongSmses() - All parts accounted for in smsGroupId "' + smsGroupId + '", emitting sms event.');
smsObj = {
// These are needed for references here and there in functions
'session': returnObj,
'pduObjs': smsGroup.pduObjs,
'from': smsGroup.pduObjs[0].params.source_addr,
'to': smsGroup.pduObjs[0].params.destination_addr,
'submitTime': new Date(),
'message': '',
'dlr': Boolean(smsGroup.pduObjs[0].params.registered_delivery),
'sendResp': smsResp,
'sendDlr': smsDlr
};
// Concatenate all the parts messages to one and set references to the session
// First we need to sort the parts, since they can come in random order
smsObj.pduObjs.sort(sortLongSmsPdus);
i = 0;
while (smsObj.pduObjs[i] !== undefined) {
curPduObj = smsObj.pduObjs[i];
curPduObj.session = returnObj;
smsObj.message += utils.decode(curPduObj.params.short_message, curPduObj.params.data_coding, curPduObj.params.short_message[0]);
i ++;
}
console.log('newObj:');
console.log(newObj);
});
});
returnObj.emit('sms', smsObj);
} else if (moment(new Date()).diff(smsGroup.created, 'hours') > 24) {
log.info('larvitsmpp: lib/session.js: session() - returnObj.checkLongSmses() - smsGroupId "' + smsGroupId + '" is removed from returnObj.longSmses due to being older than 24 hours.');
returnObj.send(dlrPduObj, function(err, retPduObj) {
console.log('WHATTA WHATTA');
console.log(retPduObj);
if (typeof callback === 'function') {
callback(err, retPduObj.params.message_id, retPduObj);
delete returnObj.longSmses[smsGroupId];
}
});
}
};
// Handle incomming commands.
@@ -384,7 +557,7 @@ function session(sock) {
// TLV message_state must exists
if (pduObj.tlvs.message_state === undefined) {
log.info('larvitsmpp: lib/session.js: session() - returnObj.deliverSm() - TLV message_state is missing. SeqNr: ' + pduObj.seqNr);
log.info('larvitsmpp: lib/session.js: session() - returnObj.handleCmd.deliver_sm() - TLV message_state is missing. SeqNr: ' + pduObj.seqNr);
returnObj.sendReturn(pduObj, 'ESME_RINVTLVSTREAM');
return;
@@ -392,7 +565,7 @@ function session(sock) {
// TLV message_state needs to be valid
if (defs.constsById.MESSAGE_STATE[pduObj.tlvs.message_state.tagValue] === undefined) {
log.info('larvitsmpp: lib/session.js: session() - returnObj.deliverSm() - Invalid TLV message_state: "' + pduObj.tlvs.message_state.tagValue + '". SeqNr: ' + pduObj.seqNr);
log.info('larvitsmpp: lib/session.js: session() - returnObj.handleCmd.deliver_sm() - Invalid TLV message_state: "' + pduObj.tlvs.message_state.tagValue + '". SeqNr: ' + pduObj.seqNr);
returnObj.sendReturn(pduObj, 'ESME_RINVTLVSTREAM');
return;
@@ -400,7 +573,7 @@ function session(sock) {
// TLV receipted_message_id must exist
if (pduObj.tlvs.receipted_message_id === undefined) {
log.info('larvitsmpp: lib/session.js: session() - returnObj.deliverSm() - TLV receipted_message_id is missing. SeqNr: ' + pduObj.seqNr);
log.info('larvitsmpp: lib/session.js: session() - returnObj.handleCmd.deliver_sm() - TLV receipted_message_id is missing. SeqNr: ' + pduObj.seqNr);
returnObj.sendReturn(pduObj, 'ESME_RINVTLVSTREAM');
return;
@@ -427,25 +600,28 @@ function session(sock) {
returnObj.handleCmd.submit_sm = function(pduObj) {
var smsObj = {};
// If esm_class is 0x40 it means this is just a part of a larger message
if (pduObj.params.esm_class === 0x40) {
returnObj.longSms(pduObj);
return; // Long messages should not get handled here at all, so cancel execution here
}
smsObj = {
// These are needed for references here and there in functions
'session': returnObj,
'pduObj': pduObj,
'from': pduObj.params.source_addr,
'to': pduObj.params.destination_addr,
'submitTime': new Date(),
'message': pduObj.params.short_message,
'dlr': Boolean(pduObj.params.registered_delivery)
'dlr': Boolean(pduObj.params.registered_delivery),
'sendResp': smsResp,
'sendDlr': smsDlr
};
function smsReceived(smsData) {
if (smsData === undefined) {
smsData = {};
}
smsObj.smsId = smsData.smsId;
returnObj.sendReturn(pduObj, 'ESME_ROK', {'message_id': smsObj.smsId});
}
returnObj.emit('sms', smsObj, smsReceived);
returnObj.emit('sms', smsObj);
};
// Handle incoming unbind
@@ -534,7 +710,7 @@ function session(sock) {
} else {
log.verbose('larvitsmpp: lib/session.js: session() - returnObj.on(incomingPdu) - Incoming PDU parsed. Seqnr: ' + pduObj.seqNr + ' cmd: ' + pduObj.cmdName + ' cmdStatus: ' + pduObj.cmdStatus + ' hex: ' + pdu.toString('hex'));
if (pduObj.isResponse()) {
if (pduObj.isResp()) {
// We do this so we can remove the dynamic event listeners to not have a memory leak
returnObj.emit('incomingPduObj' + pduObj.seqNr, pduObj);