'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 } };