Splitted up module to multiple files
This commit is contained in:
+351
@@ -0,0 +1,351 @@
|
||||
'use strict';
|
||||
|
||||
var log = require('winston'),
|
||||
events = require('events'),
|
||||
smppUtils = require('./utils'),
|
||||
defs = require('./defs');
|
||||
|
||||
/**
|
||||
* Generic session function
|
||||
*
|
||||
* @param obj sock - socket object
|
||||
* @return obj (returnObj)
|
||||
*/
|
||||
function session(sock) {
|
||||
var returnObj = new events.EventEmitter();
|
||||
|
||||
log.silly('larvitsmpp: lib/session.js: session() - New session started from ' + sock.remoteAddress + ':' + sock.remotePort);
|
||||
|
||||
returnObj.loggedIn = false;
|
||||
|
||||
// Sequence number used for commands initiated from us
|
||||
returnObj.ourSeqNr = 1;
|
||||
|
||||
// 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) {
|
||||
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)) {
|
||||
smppUtils.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;
|
||||
}
|
||||
|
||||
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'));
|
||||
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 sequence number is set and is correct
|
||||
if ( ! Buffer.isBuffer(pdu)) {
|
||||
pdu.seqNr = returnObj.ourSeqNr;
|
||||
}
|
||||
|
||||
// Make sure the pdu is an object
|
||||
if (Buffer.isBuffer(pdu)) {
|
||||
smppUtils.pduToObj(pdu, function(err, pduObj) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
returnObj.send(pduObj, closeAfterSend, callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug('larvitsmpp: lib/session.js: session() - returnObj.send() - Sending PDU to remote. cmdName: ' + pdu.cmdName + ' seqNr: ' + pdu.seqNr);
|
||||
|
||||
// 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('larvitsmpp: lib/session.js: session() - returnObj.send() - Given pduObj is a response, use sendReturn() instead. cmdName: ' + pduObj.cmdName);
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// When the return is fetched, call the callback
|
||||
returnObj.on('incomingPdu' + pduObj.seqNr, function(incPduObj) {
|
||||
|
||||
log.debug('larvitsmpp: lib/session.js: session() - returnObj.send() - returnObj.on(incomingPdu) - cmdName: ' + incPduObj.cmdName + ' seqNr: ' + incPduObj.seqNr + ' cmdStatus: ' + incPduObj.cmdStatus);
|
||||
|
||||
// Clean up by removing this listener or else it will lurk along forever
|
||||
returnObj.removeAllListeners('incomingPdu' + pduObj.seqNr);
|
||||
|
||||
// Make sure this is the actual response to the sent PDU
|
||||
if (incPduObj.isResponse() && incPduObj.seqNr === pduObj.seqNr) {
|
||||
callback(null, incPduObj);
|
||||
|
||||
if (closeAfterSend) {
|
||||
returnObj.closeSocket();
|
||||
}
|
||||
} else {
|
||||
err = new Error('larvitsmpp: lib/session.js: session() - returnObj.send() - returnObj.on(incomingPdu) - 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);
|
||||
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 bol closeAfterSend - if true will close the socket after sending (OPTIONAL)
|
||||
* @param func callback(err) (OPTIONAL)
|
||||
*/
|
||||
returnObj.sendReturn = function(pdu, status, closeAfterSend, callback) {
|
||||
if (typeof closeAfterSend === 'function') {
|
||||
callback = closeAfterSend;
|
||||
closeAfterSend = undefined;
|
||||
}
|
||||
|
||||
smppUtils.pduReturn(pdu, status, 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;
|
||||
}
|
||||
|
||||
returnObj.sockWrite(retPdu, closeAfterSend);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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, smsId, retPduObj)
|
||||
*/
|
||||
returnObj.sendSms = function(smsOptions, callback) {
|
||||
var pduObj = {};
|
||||
|
||||
pduObj.cmdName = 'submit_sm';
|
||||
pduObj.params = {
|
||||
'source_addr': smsOptions.from,
|
||||
'destination_addr': smsOptions.to,
|
||||
'short_message': smsOptions.message
|
||||
};
|
||||
|
||||
// Request DLRs!
|
||||
if (smsOptions.dlr) {
|
||||
pduObj.params.registered_delivery = 0x01;
|
||||
}
|
||||
|
||||
returnObj.send(pduObj, function(err, retPduObj) {
|
||||
if (typeof callback === 'function') {
|
||||
callback(err, retPduObj.params.message_id, retPduObj);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Handle incoming deliver_sm
|
||||
returnObj.deliverSm = function(pduObj) {
|
||||
var dlrObj;
|
||||
|
||||
// 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);
|
||||
returnObj.sendReturn(pduObj, 'ESME_RINVTLVSTREAM');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
returnObj.sendReturn(pduObj, 'ESME_RINVTLVSTREAM');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
returnObj.sendReturn(pduObj, 'ESME_RINVTLVSTREAM');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dlrObj = {
|
||||
'statusMsg': defs.constsById.MESSAGE_STATE[pduObj.tlvs.message_state.tagValue],
|
||||
'statusId': pduObj.tlvs.message_state.tagValue,
|
||||
'smsId': pduObj.tlvs.receipted_message_id.tagValue
|
||||
};
|
||||
|
||||
returnObj.emit('dlr', dlrObj, pduObj);
|
||||
returnObj.sendReturn(pduObj);
|
||||
};
|
||||
|
||||
// Handle incoming submit_sm
|
||||
returnObj.submitSm = function(pduObj) {
|
||||
var smsObj = {};
|
||||
|
||||
smsObj = {
|
||||
'from': pduObj.params.source_addr,
|
||||
'to': pduObj.params.destination_addr,
|
||||
'message': pduObj.params.short_message,
|
||||
'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
|
||||
returnObj.login = function() {
|
||||
log.info('larvitsmpp: lib/session.js: session() - login() - Dummy login function ran, this might be a mistake');
|
||||
returnObj.loggedIn = true;
|
||||
};
|
||||
|
||||
// Dummy method - should be used by serverSession or clientSession
|
||||
returnObj.resetEnqLinkTimer = function() {
|
||||
log.silly('larvitsmpp: lib/session.js: session() - resetEnqLinkTimer() - Resetting the kill timer');
|
||||
};
|
||||
|
||||
returnObj.enquireLink = function(pduObj) {
|
||||
log.silly('larvitsmpp: lib/session.js: session() - enquireLink() - Enquiring link');
|
||||
returnObj.resetEnqLinkTimer();
|
||||
returnObj.sendReturn(pduObj);
|
||||
};
|
||||
|
||||
returnObj.unbind = function() {
|
||||
returnObj.send({
|
||||
'cmdName': 'unbind'
|
||||
}, true);
|
||||
};
|
||||
|
||||
// Add a 'data' event handler to this instance of socket
|
||||
sock.on('data', function(pduBuf) {
|
||||
// Pass the data along to the returnObj
|
||||
returnObj.emit('data', pduBuf);
|
||||
|
||||
// Reset the enquire link timer
|
||||
returnObj.resetEnqLinkTimer();
|
||||
|
||||
log.silly('larvitsmpp: lib/session.js: session() - sock.on(data) - Incoming PDU: ' + pduBuf.toString('hex'));
|
||||
|
||||
smppUtils.pduToObj(pduBuf, function(err, pduObj) {
|
||||
if (err) {
|
||||
log.warn('larvitsmpp: lib/session.js: session() - Invalid PDU. ' + err.message);
|
||||
|
||||
returnObj.closeSocket();
|
||||
} else {
|
||||
log.verbose('larvitsmpp: lib/session.js: session() - sock.on(data) - Incoming PDU. Seqnr: ' + pduObj.seqNr + ' cmd: ' + pduObj.cmdName + ' cmdStatus: ' + pduObj.cmdStatus + ' hex: ' + pduBuf.toString('hex'));
|
||||
|
||||
if (pduObj.isResponse()) {
|
||||
// We do this so we can remove the dynamic event listeners to not have a memory leak
|
||||
returnObj.emit('incomingPdu' + pduObj.seqNr, pduObj);
|
||||
} else {
|
||||
returnObj.emit('incomingPdu', pduObj);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Add a 'close' event handler to this instance of socket
|
||||
sock.on('close', function() {
|
||||
returnObj.emit('close');
|
||||
log.debug('larvitsmpp: lib/session.js: session() - socket closed');
|
||||
});
|
||||
|
||||
return returnObj;
|
||||
}
|
||||
|
||||
// Expose some functions
|
||||
exports = module.exports = session;
|
||||
Reference in New Issue
Block a user