openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
266 lines (238 loc) • 7.24 kB
JavaScript
var Channel, Channels, Q, adaptSocketRequest, authorisation, config, datastore, http, logger, net, newKey, startListening, stopTCPServers, tcpServers, tls, tlsAuthentication;
http = require('http');
net = require('net');
tls = require('tls');
config = require("./config/config");
config.tcpAdapter = config.get('tcpAdapter');
logger = require("winston");
Channels = require('./model/channels');
Channel = Channels.Channel;
Q = require("q");
tlsAuthentication = require("./middleware/tlsAuthentication");
authorisation = require("./middleware/authorisation");
tcpServers = [];
newKey = 0;
datastore = {};
process.on('message', function(msg) {
if (msg.type === 'start-tcp-channel') {
logger.debug("Recieved message to start tcp channel: " + msg.channelID);
return exports.startupTCPServer(msg.channelID, function() {});
} else if (msg.type === 'stop-tcp-channel') {
logger.debug("Recieved message to stop tcp channel: " + msg.channelID);
return exports.stopServerForChannel(msg.channelID, function() {});
}
});
exports.popTransaction = function(key) {
var res;
res = datastore["" + key];
delete datastore["" + key];
return res;
};
startListening = function(channel, tcpServer, host, port, callback) {
tcpServer.listen(port, host, function() {
tcpServers.push({
channelID: channel._id,
server: tcpServer
});
return callback(null);
});
return tcpServer.on('error', function(err) {
return logger.error(err + ' Host: ' + host + ' Port: ' + port);
});
};
exports.notifyMasterToStartTCPServer = function(channelID, callback) {
logger.debug("Sending message to master to start tcp channel: " + channelID);
return process.send({
type: 'start-tcp-channel',
channelID: channelID
});
};
exports.startupTCPServer = function(channelID, callback) {
var existingServer, handler, i, len;
for (i = 0, len = tcpServers.length; i < len; i++) {
existingServer = tcpServers[i];
if (existingServer.channelID.equals(channelID)) {
return callback(null);
}
}
handler = function(sock) {
return Channel.findById(channelID, function(err, channel) {
if (err) {
return logger.error(err);
}
sock.on('data', function(data) {
return adaptSocketRequest(channel, sock, "" + data);
});
return sock.on('error', function(err) {
return logger.error(err);
});
});
};
return Channel.findById(channelID, function(err, channel) {
var host, port, tcpServer;
host = channel.tcpHost || '0.0.0.0';
port = channel.tcpPort;
if (!port) {
return callback("Channel " + channel.name + " (" + channel._id + "): TCP port not defined");
}
if (channel.type === 'tls') {
return tlsAuthentication.getServerOptions(true, function(err, options) {
var tcpServer;
if (err) {
return callback(err);
}
tcpServer = tls.createServer(options, handler);
return startListening(channel, tcpServer, host, port, function(err) {
if (err) {
return callback(err);
} else {
logger.info("Channel " + channel.name + " (" + channel._id + "): TLS server listening on port " + port);
return callback(null);
}
});
});
} else if (channel.type === 'tcp') {
tcpServer = net.createServer(handler);
return startListening(channel, tcpServer, host, port, function(err) {
if (err) {
return callback(err);
} else {
logger.info("Channel " + channel.name + " (" + channel._id + "): TCP server listening on port " + port);
return callback(null);
}
});
} else {
return callback("Cannot handle " + channel.type + " channels");
}
});
};
exports.startupServers = function(callback) {
return Channel.find({
$or: [
{
type: 'tcp'
}, {
type: 'tls'
}
]
}, function(err, channels) {
var channel, fn, i, len, promises;
if (err) {
return callback(err);
}
promises = [];
fn = function(channel) {
var defer;
if (Channels.isChannelEnabled(channel)) {
defer = Q.defer();
exports.startupTCPServer(channel._id, function(err) {
if (err) {
return callback(err);
}
return defer.resolve();
});
return promises.push(defer.promise);
}
};
for (i = 0, len = channels.length; i < len; i++) {
channel = channels[i];
fn(channel);
}
return (Q.all(promises)).then(function() {
return callback(null);
});
});
};
adaptSocketRequest = function(channel, sock, socketData) {
var options, req;
options = {
hostname: config.tcpAdapter.httpReceiver.host,
port: config.tcpAdapter.httpReceiver.httpPort,
path: '/',
method: 'POST'
};
req = http.request(options, function(res) {
var response;
response = '';
res.on('data', function(data) {
return response += data;
});
return res.on('end', function() {
if (sock.writable) {
return sock.write(response);
}
});
});
req.on("error", function(err) {
return logger.error(err);
});
datastore["" + newKey] = {};
datastore["" + newKey].data = socketData;
datastore["" + newKey].channel = channel;
req.write("" + newKey);
newKey++;
if (newKey === Number.MAX_VALUE) {
newKey = 0;
}
return req.end();
};
stopTCPServers = function(servers, callback) {
var fn, i, len, promises, server;
promises = [];
fn = function(server) {
var defer;
defer = Q.defer();
server.server.close(function(err) {
if (err) {
logger.error("Could not close tcp server: " + err);
return defer.reject(err);
} else {
logger.info("Channel " + server.channelID + ": Stopped TCP/TLS server");
return defer.resolve();
}
});
return promises.push(defer.promise);
};
for (i = 0, len = servers.length; i < len; i++) {
server = servers[i];
fn(server);
}
return (Q.all(promises)).then(function() {
return callback();
});
};
exports.stopServers = function(callback) {
return stopTCPServers(tcpServers, function() {
tcpServers = [];
return callback();
});
};
exports.notifyMasterToStopTCPServer = function(channelID, callback) {
logger.debug("Sending message to master to stop tcp channel: " + channelID);
return process.send({
type: 'stop-tcp-channel',
channelID: channelID
});
};
exports.stopServerForChannel = function(channelID, callback) {
var i, len, notStoppedTcpServers, server, serverDetails;
server = null;
notStoppedTcpServers = [];
for (i = 0, len = tcpServers.length; i < len; i++) {
serverDetails = tcpServers[i];
if (serverDetails.channelID.equals(channelID)) {
server = serverDetails;
} else {
notStoppedTcpServers.push(serverDetails);
}
}
if (!server) {
return callback("Server for channel " + channelID + " not running");
}
tcpServers = notStoppedTcpServers;
return stopTCPServers([server], callback);
};
if (process.env.NODE_ENV === "test") {
exports.tcpServers = tcpServers;
}
//# sourceMappingURL=tcpAdapter.js.map