Just moved code around for some minor optimization
This commit is contained in:
+391
-376
@@ -60,13 +60,13 @@ function smsResp(status, callback) {
|
||||
localSmsId = sms.smsId;
|
||||
}
|
||||
|
||||
tasks.push(async.apply(
|
||||
sms.session.sendReturn,
|
||||
tasks[i] = sms.session.sendReturn.bind(
|
||||
sms.session,
|
||||
sms.pduObjs[i].pduObj,
|
||||
status,
|
||||
{'message_id': localSmsId},
|
||||
false
|
||||
));
|
||||
);
|
||||
|
||||
i ++;
|
||||
}
|
||||
@@ -155,6 +155,385 @@ function smsDlr(status, callback) {
|
||||
sms.session.send(dlrPduObj, false, callback);
|
||||
}
|
||||
|
||||
function incOurSeqNr() {
|
||||
this.ourSeqNr = this.ourSeqNr + 1;
|
||||
|
||||
// If we pass the maximum, start over at 1
|
||||
if (this.ourSeqNr > 2147483646) {
|
||||
this.ourSeqNr = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the socket
|
||||
* Always use this function to close the socket so we get it on log
|
||||
*/
|
||||
function closeSocket() {
|
||||
log.verbose('larvitsmpp: lib/session.js: closeSocket() - Closing socket for ' + this.sock.remoteAddress + ':' + this.sock.remotePort);
|
||||
if (this.enqLinkTimer) {
|
||||
log.debug('larvitsmpp: lib/session.js: closeSocket() - enqLinkTimer found, clearing.');
|
||||
clearTimeout(this.enqLinkTimer);
|
||||
}
|
||||
this.sock.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write PDU to socket
|
||||
*
|
||||
* @param buf or obj pdu - can also take PDU object
|
||||
* @param bol closeAfterSend - if true will close the socket after sending
|
||||
*/
|
||||
function sockWrite(pdu, closeAfterSend) {
|
||||
var that = this;
|
||||
|
||||
if ( ! Buffer.isBuffer(pdu)) {
|
||||
utils.objToPdu(pdu, function(err, buffer) {
|
||||
if (err) {
|
||||
log.warn('larvitsmpp: lib/session.js: sockWrite() - Could not convert PDU to buffer');
|
||||
that.closeSocket();
|
||||
return;
|
||||
}
|
||||
|
||||
that.sockWrite(buffer);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
log.verbose('larvitsmpp: lib/session.js: sockWrite() - sending PDU. SeqNr: ' + pdu.readUInt32BE(12) + ' cmd: ' + defs.cmdsById[pdu.readUInt32BE(4)].command + ' cmdStatus: ' + defs.errorsById[parseInt(pdu.readUInt32BE(8))] + ' hex: ' + pdu.toString('hex'));
|
||||
} catch (e) {
|
||||
log.error('larvitsmpp: lib/session.js: sockWrite() - PDU buffer is invalid. Buffer hex: "' + pdu.toString('hex') + '"');
|
||||
return;
|
||||
}
|
||||
|
||||
this.sock.write(pdu);
|
||||
|
||||
if (closeAfterSend) {
|
||||
this.closeSocket();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a PDU to the remote
|
||||
*
|
||||
* @param buf or obj pdu
|
||||
* @param bol closeAfterSend - Will close after return is fetched. Defaults to false (OPTIONAL)
|
||||
* @param func callback(err, retPdu) (OPTIONAL)
|
||||
*/
|
||||
function send(pdu, closeAfterSend, callback) {
|
||||
var pduObj = pdu,
|
||||
err = null,
|
||||
that = this;
|
||||
|
||||
// Make sure the pdu is an object
|
||||
if (Buffer.isBuffer(pdu)) {
|
||||
utils.pduToObj(pdu, function(err, pduObj) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
that.send(pduObj, closeAfterSend, callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the sequence number is set and is correct
|
||||
pduObj.seqNr = this.ourSeqNr;
|
||||
|
||||
log.debug('larvitsmpp: lib/session.js: send() - Sending PDU to remote. pduObj: ' + JSON.stringify(pduObj));
|
||||
|
||||
// If closeAndSend is omitted, put callback in its place
|
||||
if (typeof closeAfterSend === 'function') {
|
||||
callback = closeAfterSend;
|
||||
closeAfterSend = undefined;
|
||||
}
|
||||
|
||||
// Make sure the callack is a function
|
||||
if (typeof callback !== 'function') {
|
||||
callback = function(){};
|
||||
}
|
||||
|
||||
// Response PDUs are not allowed with the send() command, they should use the sendReturn()
|
||||
if (pduObj.cmdName.substring(pduObj.cmdName - 5) === '_resp') {
|
||||
err = new Error('Given pduObj is a response, use sendReturn() instead. cmdName: ' + pduObj.cmdName);
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// When the return is fetched, call the callback
|
||||
this.on('incomingPduObj' + pduObj.seqNr, function(incPduObj) {
|
||||
|
||||
log.debug('larvitsmpp: lib/session.js: send() - this.on(incomingPduObj) - cmdName: ' + incPduObj.cmdName + ' seqNr: ' + incPduObj.seqNr + ' cmdStatus: ' + incPduObj.cmdStatus);
|
||||
|
||||
// Make sure this is the actual response to the sent PDU
|
||||
if (incPduObj.isResp() && incPduObj.seqNr === pduObj.seqNr) {
|
||||
callback(null, incPduObj);
|
||||
|
||||
if (closeAfterSend) {
|
||||
that.closeSocket();
|
||||
}
|
||||
} else {
|
||||
err = new Error('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);
|
||||
}
|
||||
});
|
||||
|
||||
// Increase our internal sequence number
|
||||
this.incOurSeqNr();
|
||||
|
||||
// Write the PDU to socket
|
||||
this.sockWrite(pduObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (OPTIONAL)
|
||||
* @param obj params (OPTIONAL)
|
||||
* @param bol closeAfterSend - if true will close the socket after sending (OPTIONAL)
|
||||
* @param func callback(err, retPdu) (OPTIONAL)
|
||||
*/
|
||||
function sendReturn(pdu, status, params, closeAfterSend, callback) {
|
||||
var that = this;
|
||||
|
||||
if (typeof params === 'function') {
|
||||
callback = params;
|
||||
params = undefined;
|
||||
closeAfterSend = undefined;
|
||||
}
|
||||
|
||||
if (typeof closeAfterSend === 'function') {
|
||||
callback = closeAfterSend;
|
||||
closeAfterSend = undefined;
|
||||
}
|
||||
|
||||
utils.pduReturn(pdu, status, params, function(err, retPdu) {
|
||||
if (err) {
|
||||
log.error('larvitsmpp: lib/session.js: sendReturn() - Could not create return PDU: ' + err.message);
|
||||
that.closeSocket();
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(err);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
log.silly('larvitsmpp: lib/session.js: sendReturn() - Sending return PDU: ' + retPdu.toString('hex'));
|
||||
|
||||
that.sockWrite(retPdu, closeAfterSend);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(null, retPdu);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, smsIds, retPduObjs)
|
||||
*/
|
||||
function sendSms(smsOptions, callback) {
|
||||
var pduObj = {};
|
||||
|
||||
pduObj.cmdName = 'submit_sm';
|
||||
pduObj.params = {
|
||||
'source_addr_ton': 1, // Default to international format
|
||||
'source_addr': smsOptions.from,
|
||||
'destination_addr': smsOptions.to,
|
||||
'short_message': smsOptions.message
|
||||
};
|
||||
|
||||
// Request DLRs!
|
||||
if (smsOptions.dlr) {
|
||||
pduObj.params.registered_delivery = 0x01;
|
||||
}
|
||||
|
||||
// Check if we must split this message into multiple
|
||||
if (utils.bitCount(smsOptions.message) > 1120) {
|
||||
this.sendLongSms(smsOptions, callback);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug('larvitsmpp: lib/session.js: sendSms() - pduObj: ' + JSON.stringify(pduObj));
|
||||
|
||||
this.send(pduObj, function(err, retPduObj) {
|
||||
if (typeof callback === 'function') {
|
||||
callback(err, [retPduObj.params.message_id], [retPduObj]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a longer SMS than 1120 bits
|
||||
*
|
||||
* @param obj smsOptions
|
||||
* from - alphanum or international format
|
||||
* to - international format
|
||||
* message - string
|
||||
* dlr - boolean defaults to false
|
||||
* @param func callback(err, smsId, retPduObj)
|
||||
*/
|
||||
function sendLongSms(smsOptions, callback) {
|
||||
var that = this,
|
||||
smsIds = [],
|
||||
retPduObjs = [],
|
||||
msgs = utils.splitMsg(smsOptions.message),
|
||||
encoding = defs.encodings.detect(smsOptions.message); // Set encoding once for all message parts
|
||||
|
||||
function sendPart(i) {
|
||||
var pduObj = {
|
||||
'cmdName': 'submit_sm',
|
||||
'params': {
|
||||
'source_addr_ton': 1, // Default to international format
|
||||
'esm_class': 0x40, // This indicates that there is a UDH in the short_message
|
||||
'source_addr': smsOptions.from,
|
||||
'destination_addr': smsOptions.to,
|
||||
'data_coding': defs.consts.ENCODING[encoding],
|
||||
'short_message': msgs[i],
|
||||
'sm_length': msgs[i].length
|
||||
}
|
||||
};
|
||||
|
||||
// Request DLRs!
|
||||
if (smsOptions.dlr) {
|
||||
pduObj.params.registered_delivery = 0x01;
|
||||
}
|
||||
|
||||
log.debug('larvitsmpp: lib/session.js: sendLongSms() - pduObj: ' + JSON.stringify(pduObj));
|
||||
|
||||
that.send(pduObj, function(err, retPduObj) {
|
||||
smsIds.push(retPduObj.params.message_id);
|
||||
retPduObjs.push(retPduObj);
|
||||
|
||||
log.silly('larvitsmpp: lib/session.js: sendLongSms() - Got callback from that.send()');
|
||||
|
||||
if (typeof callback === 'function' && smsIds.length === msgs.length) {
|
||||
log.silly('larvitsmpp: lib/session.js: sendLongSms() - All callbacks returned, run the parent callback.');
|
||||
callback(err, smsIds, retPduObjs);
|
||||
}
|
||||
});
|
||||
|
||||
if (msgs[i + 1] !== undefined) {
|
||||
sendPart(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
sendPart(0);
|
||||
}
|
||||
|
||||
// Store long smses in the temporary storage
|
||||
function longSms(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 (this.longSmses[longSmsId] === undefined) {
|
||||
this.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 {
|
||||
this.longSmses[longSmsId].pduObjs.push({
|
||||
'partNr': pduObj.params.short_message[5], // We save this here to easier sort the array later on
|
||||
'pduObj': pduObj
|
||||
});
|
||||
}
|
||||
|
||||
// Check the long messages tmp storage to see if we should handle them
|
||||
this.checkLongSmses();
|
||||
}
|
||||
|
||||
// Walk through the long sms storage to investigate if we can send complete messages along
|
||||
// or should remove old ones
|
||||
function checkLongSmses() {
|
||||
var that = this,
|
||||
smsGroupId,
|
||||
smsGroup,
|
||||
smsObj,
|
||||
i,
|
||||
curPduObj;
|
||||
|
||||
log.silly('larvitsmpp: lib/session.js: checkLongSmses() - Running');
|
||||
|
||||
// Sort function to sort group parts
|
||||
function sortLongSmsPdus(a, b) {
|
||||
if (a.partNr < b.partNr) {
|
||||
return - 1;
|
||||
}
|
||||
|
||||
if (a.partNr > b.partNr) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Call when complete SMS is received
|
||||
function smsReceived() {
|
||||
that.emit('sms', smsObj);
|
||||
|
||||
// This needs to be ran if DLRs are sent for these messages
|
||||
delete that.longSmses[smsGroupId];
|
||||
}
|
||||
|
||||
for (smsGroupId in this.longSmses) {
|
||||
smsGroup = this.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: checkLongSmses() - All parts accounted for in smsGroupId "' + smsGroupId + '", emitting sms event.');
|
||||
|
||||
smsObj = {
|
||||
// These are needed for references here and there in functions
|
||||
'session': that,
|
||||
'pduObjs': smsGroup.pduObjs,
|
||||
'from': smsGroup.pduObjs[0].pduObj.params.source_addr,
|
||||
'to': smsGroup.pduObjs[0].pduObj.params.destination_addr,
|
||||
'submitTime': new Date(),
|
||||
'message': '',
|
||||
'dlr': Boolean(smsGroup.pduObjs[0].pduObj.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].pduObj;
|
||||
curPduObj.session = this;
|
||||
|
||||
smsObj.message += utils.decodeMsg(curPduObj.params.short_message, curPduObj.params.data_coding, curPduObj.params.short_message[0] + 1);
|
||||
|
||||
i ++;
|
||||
}
|
||||
smsReceived();
|
||||
} else if (moment(new Date()).diff(smsGroup.created, 'hours') > 24) {
|
||||
log.info('larvitsmpp: lib/session.js: checkLongSmses() - smsGroupId "' + smsGroupId + '" is removed from this.longSmses due to being older than 24 hours.');
|
||||
|
||||
delete this.longSmses[smsGroupId];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic session function
|
||||
*
|
||||
@@ -174,222 +553,12 @@ function session(sock) {
|
||||
// Make the socket transparent via the returned emitter
|
||||
returnObj.sock = sock;
|
||||
|
||||
/**
|
||||
* Increase our sequence number
|
||||
*/
|
||||
returnObj.incOurSeqNr = function() {
|
||||
returnObj.ourSeqNr = returnObj.ourSeqNr + 1;
|
||||
|
||||
// If we pass the maximum, start over at 1
|
||||
if (returnObj.ourSeqNr > 2147483646) {
|
||||
returnObj.ourSeqNr = 1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Close the socket
|
||||
* Always use this function to close the socket so we get it on log
|
||||
*/
|
||||
returnObj.closeSocket = function() {
|
||||
log.verbose('larvitsmpp: lib/session.js: session() - closeSocket() - Closing socket for ' + sock.remoteAddress + ':' + sock.remotePort);
|
||||
if (returnObj.enqLinkTimer) {
|
||||
log.debug('larvitsmpp: lib/session.js: session() - closeSocket() - enqLinkTimer found, clearing.');
|
||||
clearTimeout(returnObj.enqLinkTimer);
|
||||
}
|
||||
sock.destroy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Write PDU to socket
|
||||
*
|
||||
* @param buf or obj pdu - can also take PDU object
|
||||
* @param bol closeAfterSend - if true will close the socket after sending
|
||||
*/
|
||||
returnObj.sockWrite = function(pdu, closeAfterSend) {
|
||||
if ( ! Buffer.isBuffer(pdu)) {
|
||||
utils.objToPdu(pdu, function(err, buffer) {
|
||||
if (err) {
|
||||
log.warn('larvitsmpp: lib/session.js: session() - sockWrite() - Could not convert PDU to buffer');
|
||||
returnObj.closeSocket();
|
||||
return;
|
||||
}
|
||||
|
||||
returnObj.sockWrite(buffer);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
log.verbose('larvitsmpp: lib/session.js: session() - sockWrite() - sending PDU. SeqNr: ' + pdu.readUInt32BE(12) + ' cmd: ' + defs.cmdsById[pdu.readUInt32BE(4)].command + ' cmdStatus: ' + defs.errorsById[parseInt(pdu.readUInt32BE(8))] + ' hex: ' + pdu.toString('hex'));
|
||||
} catch (e) {
|
||||
log.error('larvitsmpp: lib/session.js: session() - sockWrite() - PDU buffer is invalid. Buffer hex: "' + pdu.toString('hex') + '"');
|
||||
return;
|
||||
}
|
||||
|
||||
sock.write(pdu);
|
||||
|
||||
if (closeAfterSend) {
|
||||
returnObj.closeSocket();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a PDU to the remote
|
||||
*
|
||||
* @param buf or obj pdu
|
||||
* @param bol closeAfterSend - Will close after return is fetched. Defaults to false (OPTIONAL)
|
||||
* @param func callback(err, retPdu) (OPTIONAL)
|
||||
*/
|
||||
returnObj.send = function(pdu, closeAfterSend, callback) {
|
||||
var pduObj = pdu,
|
||||
err = null;
|
||||
|
||||
// Make sure the pdu is an object
|
||||
if (Buffer.isBuffer(pdu)) {
|
||||
utils.pduToObj(pdu, function(err, pduObj) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
returnObj.send(pduObj, closeAfterSend, callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the sequence number is set and is correct
|
||||
pduObj.seqNr = returnObj.ourSeqNr;
|
||||
|
||||
log.debug('larvitsmpp: lib/session.js: session() - returnObj.send() - Sending PDU to remote. pduObj: ' + JSON.stringify(pduObj));
|
||||
|
||||
// If closeAndSend is omitted, put callback in its place
|
||||
if (typeof closeAfterSend === 'function') {
|
||||
callback = closeAfterSend;
|
||||
closeAfterSend = undefined;
|
||||
}
|
||||
|
||||
// Make sure the callack is a function
|
||||
if (typeof callback !== 'function') {
|
||||
callback = function(){};
|
||||
}
|
||||
|
||||
// Response PDUs are not allowed with the send() command, they should use the sendReturn()
|
||||
if (pduObj.cmdName.substring(pduObj.cmdName - 5) === '_resp') {
|
||||
err = new Error('Given pduObj is a response, use sendReturn() instead. cmdName: ' + pduObj.cmdName);
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// When the return is fetched, call the callback
|
||||
returnObj.on('incomingPduObj' + pduObj.seqNr, function(incPduObj) {
|
||||
|
||||
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.isResp() && incPduObj.seqNr === pduObj.seqNr) {
|
||||
callback(null, incPduObj);
|
||||
|
||||
if (closeAfterSend) {
|
||||
returnObj.closeSocket();
|
||||
}
|
||||
} else {
|
||||
err = new Error('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);
|
||||
}
|
||||
});
|
||||
|
||||
// Increase our internal sequence number
|
||||
returnObj.incOurSeqNr();
|
||||
|
||||
// Write the PDU to socket
|
||||
returnObj.sockWrite(pduObj);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 (OPTIONAL)
|
||||
* @param obj params (OPTIONAL)
|
||||
* @param bol closeAfterSend - if true will close the socket after sending (OPTIONAL)
|
||||
* @param func callback(err, retPdu) (OPTIONAL)
|
||||
*/
|
||||
returnObj.sendReturn = function(pdu, status, params, closeAfterSend, callback) {
|
||||
if (typeof params === 'function') {
|
||||
callback = params;
|
||||
params = undefined;
|
||||
closeAfterSend = undefined;
|
||||
}
|
||||
|
||||
if (typeof closeAfterSend === 'function') {
|
||||
callback = closeAfterSend;
|
||||
closeAfterSend = undefined;
|
||||
}
|
||||
|
||||
utils.pduReturn(pdu, status, params, function(err, retPdu) {
|
||||
if (err) {
|
||||
log.error('larvitsmpp: lib/session.js: session() - returnObj.sendReturn() - Could not create return PDU: ' + err.message);
|
||||
returnObj.closeSocket();
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(err);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
log.silly('larvitsmpp: lib/session.js: session() - returnObj.sendReturn() - Sending return PDU: ' + retPdu.toString('hex'));
|
||||
|
||||
returnObj.sockWrite(retPdu, closeAfterSend);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(null, retPdu);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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, smsIds, retPduObjs)
|
||||
*/
|
||||
returnObj.sendSms = function(smsOptions, callback) {
|
||||
var pduObj = {};
|
||||
|
||||
pduObj.cmdName = 'submit_sm';
|
||||
pduObj.params = {
|
||||
'source_addr_ton': 1, // Default to international format
|
||||
'source_addr': smsOptions.from,
|
||||
'destination_addr': smsOptions.to,
|
||||
'short_message': smsOptions.message
|
||||
};
|
||||
|
||||
// Request DLRs!
|
||||
if (smsOptions.dlr) {
|
||||
pduObj.params.registered_delivery = 0x01;
|
||||
}
|
||||
|
||||
// Check if we must split this message into multiple
|
||||
if (utils.bitCount(smsOptions.message) > 1120) {
|
||||
returnObj.sendLongSms(smsOptions, callback);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug('larvitsmpp: lib/session.js: returnObj.sendSms() - pduObj: ' + JSON.stringify(pduObj));
|
||||
|
||||
returnObj.send(pduObj, function(err, retPduObj) {
|
||||
if (typeof callback === 'function') {
|
||||
callback(err, [retPduObj.params.message_id], [retPduObj]);
|
||||
}
|
||||
});
|
||||
};
|
||||
returnObj.incOurSeqNr = incOurSeqNr;
|
||||
returnObj.closeSocket = closeSocket;
|
||||
returnObj.sockWrite = sockWrite;
|
||||
returnObj.send = send;
|
||||
returnObj.sendReturn = sendReturn;
|
||||
returnObj.sendSms = sendSms;
|
||||
|
||||
// Temporary storage for long sms parts
|
||||
// These should be cleared if they lingre to long to avoid memory leaks
|
||||
@@ -399,163 +568,9 @@ function session(sock) {
|
||||
// We keep them like this to be able to simulate a single DLR when all parts have gotten DLRs
|
||||
returnObj.longSmsDlrs = {};
|
||||
|
||||
/**
|
||||
* Send a longer SMS than 1120 bits
|
||||
*
|
||||
* @param obj smsOptions
|
||||
* from - alphanum or international format
|
||||
* to - international format
|
||||
* message - string
|
||||
* dlr - boolean defaults to false
|
||||
* @param func callback(err, smsId, retPduObj)
|
||||
*/
|
||||
returnObj.sendLongSms = function(smsOptions, callback) {
|
||||
var smsIds = [],
|
||||
retPduObjs = [],
|
||||
msgs = utils.splitMsg(smsOptions.message),
|
||||
encoding = defs.encodings.detect(smsOptions.message); // Set encoding once for all message parts
|
||||
|
||||
function sendPart(i) {
|
||||
var pduObj = {
|
||||
'cmdName': 'submit_sm',
|
||||
'params': {
|
||||
'source_addr_ton': 1, // Default to international format
|
||||
'esm_class': 0x40, // This indicates that there is a UDH in the short_message
|
||||
'source_addr': smsOptions.from,
|
||||
'destination_addr': smsOptions.to,
|
||||
'data_coding': defs.consts.ENCODING[encoding],
|
||||
'short_message': msgs[i],
|
||||
'sm_length': msgs[i].length
|
||||
}
|
||||
};
|
||||
|
||||
// Request DLRs!
|
||||
if (smsOptions.dlr) {
|
||||
pduObj.params.registered_delivery = 0x01;
|
||||
}
|
||||
|
||||
log.debug('larvitsmpp: lib/session.js: returnObj.sendLongSms() - pduObj: ' + JSON.stringify(pduObj));
|
||||
|
||||
returnObj.send(pduObj, function(err, retPduObj) {
|
||||
smsIds.push(retPduObj.params.message_id);
|
||||
retPduObjs.push(retPduObj);
|
||||
|
||||
log.silly('larvitsmpp: lib/session.js: returnObj.sendLongSms() - Callback from returnObj.send() gotten');
|
||||
|
||||
if (typeof callback === 'function' && smsIds.length === msgs.length) {
|
||||
log.silly('larvitsmpp: lib/session.js: returnObj.sendLongSms() - All callbacks returned, run the parent callback.');
|
||||
callback(err, smsIds, retPduObjs);
|
||||
}
|
||||
});
|
||||
|
||||
if (msgs[i + 1] !== undefined) {
|
||||
sendPart(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
sendPart(0);
|
||||
};
|
||||
|
||||
// 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 (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 {
|
||||
returnObj.longSmses[longSmsId].pduObjs.push({
|
||||
'partNr': pduObj.params.short_message[5], // We save this here to easier sort the array later on
|
||||
'pduObj': pduObj
|
||||
});
|
||||
}
|
||||
|
||||
// Check the long messages tmp storage to see if we should handle them
|
||||
returnObj.checkLongSmses();
|
||||
};
|
||||
|
||||
// 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;
|
||||
|
||||
log.silly('larvitsmpp: lib/session.js: session() - returnObj.checkLongSmses() - Running');
|
||||
|
||||
// Sort function to sort group parts
|
||||
function sortLongSmsPdus(a, b) {
|
||||
if (a.partNr < b.partNr) {
|
||||
return - 1;
|
||||
}
|
||||
|
||||
if (a.partNr > b.partNr) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Call when complete SMS is received
|
||||
function smsReceived() {
|
||||
returnObj.emit('sms', smsObj);
|
||||
|
||||
// This needs to be ran if DLRs are sent for these messages
|
||||
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].pduObj.params.source_addr,
|
||||
'to': smsGroup.pduObjs[0].pduObj.params.destination_addr,
|
||||
'submitTime': new Date(),
|
||||
'message': '',
|
||||
'dlr': Boolean(smsGroup.pduObjs[0].pduObj.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].pduObj;
|
||||
curPduObj.session = returnObj;
|
||||
|
||||
smsObj.message += utils.decodeMsg(curPduObj.params.short_message, curPduObj.params.data_coding, curPduObj.params.short_message[0] + 1);
|
||||
|
||||
i ++;
|
||||
}
|
||||
smsReceived();
|
||||
} 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.');
|
||||
|
||||
delete returnObj.longSmses[smsGroupId];
|
||||
}
|
||||
}
|
||||
};
|
||||
returnObj.sendLongSms = sendLongSms;
|
||||
returnObj.longSms = longSms;
|
||||
returnObj.checkLongSmses = checkLongSmses;
|
||||
|
||||
// Handle incomming commands.
|
||||
// This is intended to be extended
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@
|
||||
"url": "https://github.com/larvit/larvitsmpp",
|
||||
"type": "git"
|
||||
},
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"readmeFilename": "README.md",
|
||||
"readme": "larvitsmpp",
|
||||
"bugs": {
|
||||
|
||||
Reference in New Issue
Block a user