goldilocks.js/lib/servers.js

108 lines
2.3 KiB
JavaScript
Raw Normal View History

'use strict';
var serversMap = module.exports._serversMap = {};
module.exports.addTcpListener = function (port, handler) {
var PromiseA = require('bluebird');
return new PromiseA(function (resolve, reject) {
var stat = serversMap[port] || serversMap[port];
if (stat) {
if (stat._closing) {
module.exports.destroyTcpListener(port);
}
else if (handler !== stat.handler) {
// we'll replace the current listener
stat.handler = handler;
resolve();
return;
}
else {
// this exact listener is already open
resolve();
return;
}
}
var enableDestroy = require('server-destroy');
var net = require('net');
var resolved;
var server = net.createServer();
stat = serversMap[port] = {
server: server
, handler: handler
, _closing: false
};
server.on('connection', function (conn) {
conn.__port = port;
conn.__proto = 'tcp';
stat.handler(conn);
});
server.on('error', function (e) {
delete serversMap[port];
if (!resolved) {
reject(e);
return;
}
if (handler.onError) {
handler.onError(e);
return;
}
throw e;
});
server.listen(port, function () {
resolved = true;
resolve();
});
enableDestroy(server); // adds .destroy
});
};
module.exports.closeTcpListener = function (port) {
var PromiseA = require('bluebird');
return new PromiseA(function (resolve) {
var stat = serversMap[port];
if (!stat) {
return;
}
stat.server.on('close', function () {
// once the clients close too
delete serversMap[port];
if (stat._closing) {
stat._closing(); // resolve
stat._closing = null;
}
stat = null;
});
stat._closing = resolve;
stat.server.close();
});
};
module.exports.destroyTcpListener = function (port) {
var stat = serversMap[port];
delete serversMap[port];
stat.server.destroy();
if (stat._closing) {
stat._closing();
stat._closing = null;
}
stat = null;
};
module.exports.listeners = {
tcp: {
add: module.exports.addTcpListener
, close: module.exports.closeTcpListener
, destroy: module.exports.destroyTcpListener
}
};