Add TLS Support

This commit is contained in:
Josef Fröhle
2016-06-22 22:06:09 +02:00
parent d5dbd74af2
commit aaf93273c5
2 changed files with 122 additions and 107 deletions
+9 -2
View File
@@ -3,6 +3,7 @@
var log = require('winston'), var log = require('winston'),
merge = require('utils-merge'), merge = require('utils-merge'),
net = require('net'), net = require('net'),
tls = require('tls'),
session = require('./session'); session = require('./session');
function login() { function login() {
@@ -94,7 +95,6 @@ function clientSession(sock, options) {
* @param func callback(err, session) * @param func callback(err, session)
*/ */
function client(options, callback) { function client(options, callback) {
var sock = new net.Socket();
// Set default options // Set default options
options = merge({ options = merge({
@@ -102,11 +102,18 @@ function client(options, callback) {
'port': 2775, 'port': 2775,
'username': 'user', 'username': 'user',
'password': 'pass', 'password': 'pass',
'tls': false,
'enqLinkTiming': 20000 // 20 sec 'enqLinkTiming': 20000 // 20 sec
}, options || {}); }, options || {});
if(options && options.tls && option.tls === true){
var sock = new tls.Socket();
} else {
var sock = new net.Socket();
}
log.debug('larvitsmpp: lib/client.js: client() - Connecting to ' + options.host + ':' + options.port); log.debug('larvitsmpp: lib/client.js: client() - Connecting to ' + options.host + ':' + options.port);
sock.connect(options.port, options.host, function() { sock.connect(options, function() {
var session = clientSession(sock, options); var session = clientSession(sock, options);
log.info('larvitsmpp: lib/client.js: client() - Connected to ' + sock.remoteAddress + ':' + sock.remotePort); log.info('larvitsmpp: lib/client.js: client() - Connected to ' + sock.remoteAddress + ':' + sock.remotePort);
+113 -105
View File
@@ -3,6 +3,7 @@
var log = require('winston'), var log = require('winston'),
merge = require('utils-merge'), merge = require('utils-merge'),
net = require('net'), net = require('net'),
tls = require('tls'),
session = require('./session'), session = require('./session'),
smppUtils = require('./utils'); smppUtils = require('./utils');
@@ -12,67 +13,67 @@ var log = require('winston'),
* @param obj pduObj * @param obj pduObj
*/ */
function login(pduObj) { function login(pduObj) {
var that = this; var that = this;
log.debug('larvitsmpp: lib/server.js: login() - Data received and session is not loggedIn'); log.debug('larvitsmpp: lib/server.js: login() - Data received and session is not loggedIn');
// Pause socket so we do not receive any other commands until we have processed the login // Pause socket so we do not receive any other commands until we have processed the login
this.sock.pause(); this.sock.pause();
// Only bind_* is accepted when the client is not logged in // Only bind_* is accepted when the client is not logged in
if (pduObj.cmdName !== 'bind_transceiver' && pduObj.cmdName !== 'bind_receiver' && pduObj.cmdName !== 'bind_transmitter') { if (pduObj.cmdName !== 'bind_transceiver' && pduObj.cmdName !== 'bind_receiver' && pduObj.cmdName !== 'bind_transmitter') {
log.debug('larvitsmpp: lib/server.js: login() - Session is not loggedIn and no bind_* command is given. Return error "ESME_RINVBNDSTS'); log.debug('larvitsmpp: lib/server.js: login() - Session is not loggedIn and no bind_* command is given. Return error "ESME_RINVBNDSTS');
smppUtils.pduReturn(pduObj, 'ESME_RINVBNDSTS', function(err, retPdu) { smppUtils.pduReturn(pduObj, 'ESME_RINVBNDSTS', function(err, retPdu) {
if (err) { if (err) {
that.closeSocket(); that.closeSocket();
return; return;
} }
that.sock.resume(); that.sock.resume();
that.sockWrite(retPdu); that.sockWrite(retPdu);
}); });
return; return;
} }
// If there is a checkuserpass(), use it to check system_id and password from the PDU // If there is a checkuserpass(), use it to check system_id and password from the PDU
if (typeof this.options.checkuserpass === 'function') { if (typeof this.options.checkuserpass === 'function') {
this.options.checkuserpass(pduObj.params.system_id, pduObj.params.password, function(err, res, userData) { this.options.checkuserpass(pduObj.params.system_id, pduObj.params.password, function(err, res, userData) {
if (err) { if (err) {
that.closeSocket(); that.closeSocket();
return; return;
} }
if ( ! res) { if ( ! res) {
log.info('larvitsmpp: lib/server.js: serverSession() - login() - Login failed! Connected host: ' + that.sock.remoteAddress + ':' + that.sock.remotePort + ' system_id: "' + pduObj.params.system_id + '"'); log.info('larvitsmpp: lib/server.js: serverSession() - login() - Login failed! Connected host: ' + that.sock.remoteAddress + ':' + that.sock.remotePort + ' system_id: "' + pduObj.params.system_id + '"');
that.sock.resume(); that.sock.resume();
that.sendReturn(pduObj, 'ESME_RBINDFAIL'); that.sendReturn(pduObj, 'ESME_RBINDFAIL');
return; return;
} }
log.verbose('larvitsmpp: lib/server.js: serverSession() - login() - Login successful! Connected host: ' + that.sock.remoteAddress + ':' + that.sock.remotePort + ' system_id: "' + pduObj.params.system_id + '"'); log.verbose('larvitsmpp: lib/server.js: serverSession() - login() - Login successful! Connected host: ' + that.sock.remoteAddress + ':' + that.sock.remotePort + ' system_id: "' + pduObj.params.system_id + '"');
that.loggedIn = true; that.loggedIn = true;
// Set additional user data to the session // Set additional user data to the session
if (userData !== undefined) { if (userData !== undefined) {
that.userData = userData; that.userData = userData;
} }
that.sock.resume(); that.sock.resume();
that.emit('login'); that.emit('login');
that.sendReturn(pduObj); that.sendReturn(pduObj);
}); });
return; return;
} }
// If we arrived here it means we are not logged in and that a bind_* event happened and no checkuserpass() method exists. Lets login! // If we arrived here it means we are not logged in and that a bind_* event happened and no checkuserpass() method exists. Lets login!
this.loggedIn = true; this.loggedIn = true;
this.sock.resume(); this.sock.resume();
this.emit('login'); this.emit('login');
this.sendReturn(pduObj); this.sendReturn(pduObj);
} }
/** /**
@@ -80,17 +81,17 @@ function login(pduObj) {
* If this is not ran within options.timeout milliseconds, this session will self terminate * If this is not ran within options.timeout milliseconds, this session will self terminate
*/ */
function resetEnqLinkTimer() { function resetEnqLinkTimer() {
var that = this; var that = this;
log.silly('larvitsmpp: lib/server.js: resetEnqLinkTimer() - Resetting the kill timer'); log.silly('larvitsmpp: lib/server.js: resetEnqLinkTimer() - Resetting the kill timer');
if (that.enqLinkTimer) { if (that.enqLinkTimer) {
clearTimeout(that.enqLinkTimer); clearTimeout(that.enqLinkTimer);
} }
that.enqLinkTimer = setTimeout(function() { that.enqLinkTimer = setTimeout(function() {
log.info('larvitsmpp: lib/server.js: resetEnqLinkTimer() - Closing session from ' + that.sock.remoteAddress + ':' + that.sock.remotePort + ' due to timeout'); log.info('larvitsmpp: lib/server.js: resetEnqLinkTimer() - Closing session from ' + that.sock.remoteAddress + ':' + that.sock.remotePort + ' due to timeout');
that.closeSocket(); that.closeSocket();
}, that.options.timeout); }, that.options.timeout);
} }
/** /**
@@ -101,42 +102,42 @@ function resetEnqLinkTimer() {
* @return obj (returnObj) * @return obj (returnObj)
*/ */
function serverSession(sock, options) { function serverSession(sock, options) {
var returnObj = session(sock); var returnObj = session(sock);
returnObj.options = options; returnObj.options = options;
returnObj.login = login; returnObj.login = login;
returnObj.resetEnqLinkTimer = resetEnqLinkTimer; returnObj.resetEnqLinkTimer = resetEnqLinkTimer;
returnObj.resetEnqLinkTimer(); returnObj.resetEnqLinkTimer();
// Handle incoming Pdu Objects // Handle incoming Pdu Objects
returnObj.on('incomingPduObj', function(pduObj) { returnObj.on('incomingPduObj', function(pduObj) {
// Call the appropriate handleCmd function // Call the appropriate handleCmd function
// Unbind is always ok // Unbind is always ok
if (pduObj.cmdName === 'unbind') { if (pduObj.cmdName === 'unbind') {
returnObj.sendReturn(pduObj, 'ESME_ROK', undefined, true); returnObj.sendReturn(pduObj, 'ESME_ROK', undefined, true);
// If client is not logged in, always run the login function // If client is not logged in, always run the login function
} else if (returnObj.loggedIn === false) { } else if (returnObj.loggedIn === false) {
log.debug('larvitsmpp: lib/server.js: serverSession() - returnObj.handleIncomingPdu() - Not logged in, running login function'); log.debug('larvitsmpp: lib/server.js: serverSession() - returnObj.handleIncomingPdu() - Not logged in, running login function');
returnObj.login(pduObj); returnObj.login(pduObj);
// Client is logged in, try to match a handling function // Client is logged in, try to match a handling function
} else if (typeof returnObj.handleCmd[pduObj.cmdName] === 'function') { } else if (typeof returnObj.handleCmd[pduObj.cmdName] === 'function') {
log.debug('larvitsmpp: lib/server.js: serverSession() - returnObj.on(incomingPduObj) - Running cmd handling function returnObj.handleCmd.' + pduObj.cmdName + '()'); log.debug('larvitsmpp: lib/server.js: serverSession() - returnObj.on(incomingPduObj) - Running cmd handling function returnObj.handleCmd.' + pduObj.cmdName + '()');
returnObj.handleCmd[pduObj.cmdName](pduObj); returnObj.handleCmd[pduObj.cmdName](pduObj);
// No command handling function is registered, return error "invalid command" // No command handling function is registered, return error "invalid command"
} else { } else {
log.info('larvitsmpp: lib/server.js: serverSession() - returnObj.on(incomingPduObj) - No handling function found for command: "' + pduObj.cmdName + '"'); log.info('larvitsmpp: lib/server.js: serverSession() - returnObj.on(incomingPduObj) - No handling function found for command: "' + pduObj.cmdName + '"');
returnObj.sendReturn(pduObj, 'ESME_RINVCMDID'); returnObj.sendReturn(pduObj, 'ESME_RINVCMDID');
} }
}); });
return returnObj; return returnObj;
} }
/** /**
@@ -146,34 +147,41 @@ function serverSession(sock, options) {
* @param func callback(err, session) * @param func callback(err, session)
*/ */
function server(options, callback) { function server(options, callback) {
if (typeof options === 'function') { if (typeof options === 'function') {
callback = options; callback = options;
options = {}; options = {};
} }
// Set default options // Set default options
options = merge({ options = merge({
'port': 2775, 'port': 2775,
'timeout': 40000 // 40 sec 'tls': false,
}, options || {}); 'timeout': 40000 // 40 sec
}, options || {});
// Create a server instance, and chain the listen function to it if(options && options.tls && option.tls === true){
// The function passed to net.createServer() becomes the event handler for the 'connection' event var tls_or_net = tls;
// The sock object the callback function receives UNIQUE for each connection } else {
net.createServer(function(sock) { var tls_or_net = net;
var returnObj = serverSession(sock, options); }
// We have a connection - a socket object is assigned to the connection automatically // Create a server instance, and chain the listen function to it
log.verbose('larvitsmpp: lib/server.js: server() - Incomming connection! From: ' + sock.remoteAddress + ':' + sock.remotePort); // The function passed to net.createServer() becomes the event handler for the 'connection' event
// The sock object the callback function receives UNIQUE for each connection
tls_or_net.createServer(options, function(sock) {
var returnObj = serverSession(sock, options);
callback(null, returnObj); // We have a connection - a socket object is assigned to the connection automatically
}).listen(options.port, options.host); log.verbose('larvitsmpp: lib/server.js: server() - Incomming connection! From: ' + sock.remoteAddress + ':' + sock.remotePort);
if (options.host !== undefined) { callback(null, returnObj);
log.info('larvitsmpp: lib/server.js: server() - Up and listening at ' + options.host + ':' + options.port); }).listen(options.port, options.host);
} else {
log.info('larvitsmpp: lib/server.js: server() - Up and listening at *:' + options.port); if (options.host !== undefined) {
} log.info('larvitsmpp: lib/server.js: server() - Up and listening at ' + options.host + ':' + options.port);
} else {
log.info('larvitsmpp: lib/server.js: server() - Up and listening at *:' + options.port);
}
} }
// Expose some functions // Expose some functions