'use strict'; module.exports.create = function (deps, config) { var PromiseA = require('bluebird'); var server; function curState() { var addr = server && server.address(); if (!addr) { return PromiseA.resolve({running: false}); } return PromiseA.resolve({ running: true , port: addr.port }); } function start(port) { if (server) { return curState(); } server = require('socksv5').createServer(function (info, accept) { accept(); }); // It would be nice if we could use `server-destroy` here, but we can't because // the socksv5 library will not give us access to any sockets it actually // handles, so we have no way of keeping track of them or closing them. server.on('close', function () { server = null; }); server.useAuth(require('socksv5').auth.None()); return new PromiseA(function (resolve, reject) { server.on('error', function (err) { if (!port && err.code === 'EADDRINUSE') { server.listen(0); } else { server = null; reject(err); } }); server.listen(port || 1080, function () { resolve(curState()); }); }); } function stop() { if (!server) { return curState(); } return new PromiseA(function (resolve, reject) { server.close(function (err) { if (err) { reject(err); } else { resolve(curState()); } }); }); } var configEnabled = false; function updateConf() { var wanted = config.socks5 && config.socks5.enabled; if (configEnabled && !wanted) { stop().catch(function (err) { console.error('failed to stop socks5 proxy on config change', err); }); configEnabled = false; } if (wanted && !configEnabled) { start(config.socks5.port).catch(function (err) { console.error('failed to start Socks5 proxy', err); }); configEnabled = true; } } process.nextTick(updateConf); return { curState , start , stop , updateConf }; };