goldilocks.js/lib/socks5-server.js

92 lines
2.1 KiB
JavaScript

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