Replaces callbacks with Promises throughout the rest of the application.
This commit is contained in:
parent
d1265253d2
commit
a74409ddb7
|
@ -3,7 +3,8 @@
|
||||||
## [4.0.0] - 2018-09-09
|
## [4.0.0] - 2018-09-09
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
- All methods now return promises instead of accepting callbacks. Methods now take advantage of async/await resulting in clearer code. Compatibility with node < v8 will be broken.
|
- All methods now return promises instead of accepting callbacks. Methods now take advantage of async/await to increase readability.
|
||||||
|
- The `logger` argument to the constructor's of all classes is now optional
|
||||||
|
|
||||||
### Removes
|
### Removes
|
||||||
- The `new_ips` and `new_ip_at` TorPool and `new_ip` TorProcess have been removed. Use `new_identites`, `new_identity_at` and `new_identity` instead.
|
- The `new_ips` and `new_ip_at` TorPool and `new_ip` TorProcess have been removed. Use `new_identites`, `new_identity_at` and `new_identity` instead.
|
||||||
|
|
|
@ -3,12 +3,11 @@ const SOCKSServer = require('./SOCKSServer');
|
||||||
const DNSServer = require('./DNSServer');
|
const DNSServer = require('./DNSServer');
|
||||||
const HTTPServer = require('./HTTPServer');
|
const HTTPServer = require('./HTTPServer');
|
||||||
const rpc = require('jrpc2');
|
const rpc = require('jrpc2');
|
||||||
const async = require('async');
|
|
||||||
|
|
||||||
class ControlServer {
|
class ControlServer {
|
||||||
constructor(logger, nconf) {
|
constructor(logger, nconf) {
|
||||||
this.torPool = new TorPool(nconf.get('torPath'), null, nconf.get('parentDataDirectory'), nconf.get('loadBalanceMethod'), nconf.get('granaxOptions'),logger);
|
this.torPool = new TorPool(nconf.get('torPath'), null, nconf.get('parentDataDirectory'), nconf.get('loadBalanceMethod'), nconf.get('granaxOptions'),logger);
|
||||||
this.logger = logger;
|
this.logger = logger || require('./winston-silent-logger');
|
||||||
this.nconf = nconf;
|
this.nconf = nconf;
|
||||||
|
|
||||||
let server = this.server = new rpc.Server();
|
let server = this.server = new rpc.Server();
|
||||||
|
@ -21,247 +20,99 @@ class ControlServer {
|
||||||
return { name: i.instance_name, dns_port: i.dns_port, socks_port: i.socks_port, process_id: i.process.pid, config: i.definition.Config, weight: i.definition.weight };
|
return { name: i.instance_name, dns_port: i.dns_port, socks_port: i.socks_port, process_id: i.process.pid, config: i.definition.Config, weight: i.definition.weight };
|
||||||
};
|
};
|
||||||
|
|
||||||
server.expose('queryInstances', (function () {
|
server.expose('queryInstances', (async () => {
|
||||||
return new Promise((resolve, reject) => {
|
if (!this.torPool)
|
||||||
if (!this.torPool)
|
throw new Error('No instances created');
|
||||||
return reject({ message: 'No pool created' });
|
|
||||||
|
|
||||||
resolve(this.torPool.instances.map(instance_info) );
|
this.torPool.instances.map(instance_info);
|
||||||
});
|
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
|
|
||||||
server.expose('queryInstanceByName', (function (instance_name) {
|
server.expose('queryInstanceByName', (async (instance_name) => {
|
||||||
return new Promise((resolve, reject) => {
|
if (!this.torPool)
|
||||||
if (!this.torPool)
|
throw new Error('No pool created');
|
||||||
return reject({ message: 'No pool created' });
|
|
||||||
|
|
||||||
let i = this.torPool.instance_by_name(instance_name);
|
let instance = this.torPool.instance_by_name(instance_name);
|
||||||
|
|
||||||
if (!i)
|
if (!instance)
|
||||||
return reject({ message: `Instance "${instance_name}"" does not exist` });
|
throw new Error(`Instance "${instance_name}"" does not exist`);
|
||||||
|
|
||||||
resolve(instance_info(i));
|
return instance_info(i)
|
||||||
});
|
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
|
|
||||||
server.expose('queryInstanceAt', (function (index) {
|
server.expose('queryInstanceAt', (async (index) => {
|
||||||
return new Promise((resolve, reject) => {
|
if (!this.torPool)
|
||||||
if (!this.torPool)
|
throw new Error('No pool created');
|
||||||
return reject({ message: 'No pool created' });
|
|
||||||
|
|
||||||
let i = this.torPool.instance_at(index);
|
let instance = this.torPool.instance_at(index);
|
||||||
|
|
||||||
if (!i)
|
if (!instance)
|
||||||
return reject({ message: `Instance at "${i}"" does not exist` });
|
throw new Error(`Instance at "${i}"" does not exist`);
|
||||||
|
|
||||||
resolve(instance_info(this.torPool.instance_at(index)));
|
return instance_info(this.torPool.instance_at(index));
|
||||||
});
|
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
|
|
||||||
server.expose('createInstances', (function (instances) {
|
server.expose('createInstances', this.torPool.create.bind(this.torPool));
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.create(instances, (error, instances) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this) );
|
|
||||||
|
|
||||||
server.expose('addInstances', (function (instances) {
|
server.expose('addInstances', this.torPool.add.bind(this.torPool));
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.add(instances, (error, instances) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this) );
|
|
||||||
|
|
||||||
server.expose('removeInstances', (function (instances) {
|
server.expose('removeInstances', this.torPool.remove.bind(this.torPool));
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.remove(instances, (error) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this) );
|
|
||||||
|
|
||||||
server.expose('removeInstanceAt', (function (instance_index) {
|
server.expose('removeInstanceAt', this.torPool.remove_at.bind(this.torPool));
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.remove_at(instance_index, (error) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this) );
|
|
||||||
|
|
||||||
server.expose('removeInstanceByName', (function (instance_name) {
|
server.expose('removeInstanceByName', this.torPool.remove_by_name.bind(this.torPool));
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.remove_by_name(instance_name, (error) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this) );
|
|
||||||
|
|
||||||
server.expose('newIdentites', (function() {
|
server.expose('newIdentites', this.torPool.new_identites.bind(this.torPool));
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.new_identites((error) => {
|
server.expose('newIdentityAt', this.torPool.new_identity_at.bind(this.torPool));
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
server.expose('newIdentityByName', this.torPool.new_identity_by_name.bind(this.torPool));
|
||||||
});
|
|
||||||
});
|
server.expose('nextInstance', (async () => this.torPool.next()).bind(this));
|
||||||
|
|
||||||
|
server.expose('closeInstances', (async () => this.torPool.exit()).bind(this));
|
||||||
|
|
||||||
|
server.expose('getDefaultTorConfig', (async () => {
|
||||||
|
return this.nconf.get('torConfig');
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
|
|
||||||
server.expose('newIdentityAt', (function(index) {
|
server.expose('setDefaultTorConfig', (async (config) => {
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.new_identity_at(index, (error) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this));
|
|
||||||
|
|
||||||
server.expose('newIdentityByName', (function(name) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.new_identity_by_name(name, (error) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this));
|
|
||||||
|
|
||||||
/* Begin Deprecated */
|
|
||||||
|
|
||||||
server.expose('newIps', (function() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.new_ips((error) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this));
|
|
||||||
|
|
||||||
server.expose('newIpAt', (function(index) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.new_ip_at(index, (error) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this));
|
|
||||||
|
|
||||||
/* End Deprecated */
|
|
||||||
|
|
||||||
server.expose('nextInstance', (function () {
|
|
||||||
this.torPool.next();
|
|
||||||
return Promise.resolve();
|
|
||||||
}).bind(this) );
|
|
||||||
|
|
||||||
server.expose('closeInstances', (function () {
|
|
||||||
this.torPool.exit();
|
|
||||||
return Promise.resolve();
|
|
||||||
}).bind(this) );
|
|
||||||
|
|
||||||
server.expose('getDefaultTorConfig', (function () {
|
|
||||||
return Promise.resolve(this.nconf.get('torConfig'));
|
|
||||||
}).bind(this));
|
|
||||||
|
|
||||||
server.expose('setDefaultTorConfig', (function (config) {
|
|
||||||
this.nconf.set('torConfig', config);
|
this.nconf.set('torConfig', config);
|
||||||
return Promise.resolve();
|
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
|
|
||||||
server.expose('setTorConfig', (function (config) {
|
server.expose('setTorConfig', (async (config) => {
|
||||||
return new Promise((resolve, reject) => {
|
await Promise.all(Object.keys(config).map((key) => {
|
||||||
async.each(Object.keys(config), function (key, next) {
|
var value = config[key];
|
||||||
var value = config[key];
|
|
||||||
|
|
||||||
this.torPool.set_config_all(key, value, next);
|
return this.torPool.set_config_all(key, value);
|
||||||
}, function (error){
|
}));
|
||||||
if (error) reject(error);
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
|
|
||||||
server.expose('getLoadBalanceMethod', (function () {
|
server.expose('getLoadBalanceMethod', (async () => {
|
||||||
return Promise.resolve(this.torPool.load_balance_method);
|
return this.torPool.load_balance_method;
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
|
|
||||||
server.expose('setLoadBalanceMethod', (function (loadBalanceMethod) {
|
server.expose('setLoadBalanceMethod', (async (loadBalanceMethod) => {
|
||||||
this.torPool.load_balance_method = loadBalanceMethod;
|
this.torPool.load_balance_method = loadBalanceMethod;
|
||||||
return Promise.resolve();
|
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
|
|
||||||
server.expose('getInstanceConfigByName', (function (name, keyword) {
|
server.expose('getInstanceConfigByName', this.torPool.get_config_by_name.bind(this.torPool));
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.get_config_by_name(name, keyword, (error, value) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve(value);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this));
|
|
||||||
|
|
||||||
server.expose('getInstanceConfigAt', (function (index, keyword) {
|
server.expose('getInstanceConfigAt', this.torPool.get_config_at.bind(this.torPool));
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.get_config_at(index, keyword, (error, value) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve(value);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this));
|
|
||||||
|
|
||||||
server.expose('setInstanceConfigByName', (function (name, keyword, value) {
|
server.expose('setInstanceConfigByName', this.torPool.set_config_by_name.bind(this.torPool));
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.set_config_by_name(name, keyword, value, (error) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this));
|
|
||||||
|
|
||||||
server.expose('setInstanceConfigAt', (function (index, keyword, value) {
|
server.expose('setInstanceConfigAt', this.torPool.set_config_at.bind(this.torPool));
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.set_config_at(index, keyword, value, (error) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this));
|
|
||||||
|
|
||||||
|
server.expose('signalAllInstances', this.torPool.signal_all.bind(this.torPool));
|
||||||
|
|
||||||
server.expose('signalAllInstances', (function (signal) {
|
server.expose('signalInstanceAt', this.torPool.signal_at.bind(this.torPool));
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.signal_all(signal, (error) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this));
|
|
||||||
|
|
||||||
server.expose('signalInstanceAt', (function (index, signal, callback) {
|
server.expose('signalInstanceByName', this.torPool.signal_by_name.bind(this.torPool));
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.signal_at(index, signal, (error) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this));
|
|
||||||
|
|
||||||
server.expose('signalInstanceByName', (function (name, signal, callback) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.torPool.signal_by_name(name, signal, (error) => {
|
|
||||||
if (error) reject(error);
|
|
||||||
else resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).bind(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listen(port, callback) {
|
listen(port) {
|
||||||
this.tcpTransport = new rpc.tcpTransport({ port });
|
this.tcpTransport = new rpc.tcpTransport({ port });
|
||||||
this.tcpTransport.listen(this.server);
|
this.tcpTransport.listen(this.server);
|
||||||
callback && callback();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
|
@ -273,28 +124,25 @@ class ControlServer {
|
||||||
return this.torPool;
|
return this.torPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
createSOCKSServer(port, callback) {
|
createSOCKSServer(port) {
|
||||||
this.socksServer = new SOCKSServer(this.torPool, this.logger);
|
this.socksServer = new SOCKSServer(this.torPool, this.logger);
|
||||||
this.socksServer.listen(port || 9050);
|
this.socksServer.listen(port || 9050);
|
||||||
this.logger.info(`[socks]: Listening on ${port}`);
|
this.logger.info(`[socks]: Listening on ${port}`);
|
||||||
this.socksServer;
|
this.socksServer;
|
||||||
callback && callback();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createHTTPServer(port, callback) {
|
createHTTPServer(port) {
|
||||||
this.httpServer = new HTTPServer(this.torPool, this.logger);
|
this.httpServer = new HTTPServer(this.torPool, this.logger);
|
||||||
this.httpServer.listen(port || 9080);
|
this.httpServer.listen(port || 9080);
|
||||||
this.logger.info(`[http]: Listening on ${port}`);
|
this.logger.info(`[http]: Listening on ${port}`);
|
||||||
this.httpServer;
|
this.httpServer;
|
||||||
callback && callback();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createDNSServer(port, callback) {
|
createDNSServer(port) {
|
||||||
this.dnsServer = new DNSServer(this.torPool, this.nconf.get('dns:options'), this.nconf.get('dns:timeout'), this.logger);
|
this.dnsServer = new DNSServer(this.torPool, this.nconf.get('dns:options'), this.nconf.get('dns:timeout'), this.logger);
|
||||||
this.dnsServer.serve(port || 9053);
|
this.dnsServer.serve(port || 9053);
|
||||||
this.logger.info(`[dns]: Listening on ${port}`);
|
this.logger.info(`[dns]: Listening on ${port}`);
|
||||||
this.dnsServer;
|
this.dnsServer;
|
||||||
callback && callback();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
const dns = require('native-dns');
|
const dns = require('native-dns');
|
||||||
const UDPServer = require('native-dns').UDPServer;
|
const { UDPServer } = require('native-dns');
|
||||||
|
|
||||||
class DNSServer extends UDPServer {
|
class DNSServer extends UDPServer {
|
||||||
constructor(tor_pool, dns_options, dns_timeout, logger) {
|
constructor(tor_pool, dns_options, dns_timeout, logger) {
|
||||||
super(dns_options);
|
super(dns_options);
|
||||||
this.logger = logger;
|
this.logger = logger || require('./winston-silent-logger');
|
||||||
this.tor_pool = tor_pool;
|
this.tor_pool = tor_pool;
|
||||||
|
|
||||||
var handle_dns_request = (req, res) => {
|
const handle_dns_request = (req, res) => {
|
||||||
let connect = (tor_instance) => {
|
let connect = (tor_instance) => {
|
||||||
for (let question of req.question) {
|
for (let question of req.question) {
|
||||||
let dns_port = (tor_instance.dns_port);
|
let dns_port = (tor_instance.dns_port);
|
||||||
|
@ -27,7 +27,7 @@ class DNSServer extends UDPServer {
|
||||||
});
|
});
|
||||||
|
|
||||||
outbound_req.on('error', (err) => {
|
outbound_req.on('error', (err) => {
|
||||||
|
this.logger.error(`[dns]: an error occured while handling ar request: ${err.message}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
const Server = http.Server;
|
|
||||||
const socks = require('socksv5');
|
|
||||||
const URL = require('url');
|
const URL = require('url');
|
||||||
|
const { Server } = http;
|
||||||
|
|
||||||
|
const socks = require('socksv5');
|
||||||
const SocksProxyAgent = require('socks-proxy-agent');
|
const SocksProxyAgent = require('socks-proxy-agent');
|
||||||
|
|
||||||
|
const TOR_ROUTER_PROXY_AGENT = 'tor-router';
|
||||||
|
|
||||||
class HTTPServer extends Server {
|
class HTTPServer extends Server {
|
||||||
constructor(tor_pool, logger) {
|
constructor(tor_pool, logger) {
|
||||||
let handle_http_connections = (req, res) => {
|
let handle_http_connections = (req, res) => {
|
||||||
let url = URL.parse(req.url);
|
let url = URL.parse(req.url);
|
||||||
url.port = url.port || 80;
|
url.port = url.port || 80;
|
||||||
|
|
||||||
var buffer = [];
|
let buffer = [];
|
||||||
|
|
||||||
function onIncomingData(chunk) {
|
function onIncomingData(chunk) {
|
||||||
buffer.push(chunk);
|
buffer.push(chunk);
|
||||||
|
@ -23,7 +26,7 @@ class HTTPServer extends Server {
|
||||||
req.on('data', onIncomingData);
|
req.on('data', onIncomingData);
|
||||||
req.on('end', preConnectClosed);
|
req.on('end', preConnectClosed);
|
||||||
req.on('error', function (err) {
|
req.on('error', function (err) {
|
||||||
logger.error("[http-proxy]: an error occured\n"+err.stack);
|
logger.error("[http-proxy]: an error occured: "+err.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
let connect = (tor_instance) => {
|
let connect = (tor_instance) => {
|
||||||
|
@ -112,7 +115,7 @@ class HTTPServer extends Server {
|
||||||
outbound_socket && outbound_socket.on('close', onClose);
|
outbound_socket && outbound_socket.on('close', onClose);
|
||||||
outbound_socket && outbound_socket.on('error', onClose);
|
outbound_socket && outbound_socket.on('error', onClose);
|
||||||
|
|
||||||
inbound_socket.write('HTTP/1.1 200 Connection Established\r\n'+'Proxy-agent: tor-router\r\n' +'\r\n');
|
inbound_socket.write(`HTTP/1.1 200 Connection Established\r\n'+'Proxy-agent: ${TOR_ROUTER_PROXY_AGENT}\r\n` +'\r\n');
|
||||||
outbound_socket.write(head);
|
outbound_socket.write(head);
|
||||||
|
|
||||||
outbound_socket.pipe(inbound_socket);
|
outbound_socket.pipe(inbound_socket);
|
||||||
|
@ -130,7 +133,7 @@ class HTTPServer extends Server {
|
||||||
super(handle_http_connections);
|
super(handle_http_connections);
|
||||||
this.on('connect', handle_connect_connections);
|
this.on('connect', handle_connect_connections);
|
||||||
|
|
||||||
this.logger = logger;
|
this.logger = logger || require('./winston-silent-logger');
|
||||||
this.tor_pool = tor_pool;
|
this.tor_pool = tor_pool;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const socks = require('socksv5');
|
const socks = require('socksv5');
|
||||||
const SOCKS5Server = socks.Server;
|
const { Server } = socks;
|
||||||
|
|
||||||
class SOCKSServer extends SOCKS5Server{
|
class SOCKSServer extends Server{
|
||||||
constructor(tor_pool, logger) {
|
constructor(tor_pool, logger) {
|
||||||
let handleConnection = (info, accept, deny) => {
|
let handleConnection = (info, accept, deny) => {
|
||||||
let inbound_socket = accept(true);
|
let inbound_socket = accept(true);
|
||||||
|
@ -67,7 +67,7 @@ class SOCKSServer extends SOCKS5Server{
|
||||||
|
|
||||||
super(handleConnection);
|
super(handleConnection);
|
||||||
|
|
||||||
this.logger = logger;
|
this.logger = logger || require('./winston-silent-logger');;
|
||||||
|
|
||||||
this.useAuth(socks.auth.None());
|
this.useAuth(socks.auth.None());
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,19 +101,20 @@ class TorProcess extends EventEmitter {
|
||||||
let controlPort = this._control_port = await getPort();
|
let controlPort = this._control_port = await getPort();
|
||||||
|
|
||||||
let options = {
|
let options = {
|
||||||
DNSPort: `127.0.0.1:${context.dnsPort}`,
|
DNSPort: `127.0.0.1:${dnsPort}`,
|
||||||
SocksPort: `127.0.0.1:${context.socksPort}`,
|
SocksPort: `127.0.0.1:${socksPort}`,
|
||||||
ControlPort: `127.0.0.1:${context.controlPort}`,
|
ControlPort: `127.0.0.1:${controlPort}`,
|
||||||
HashedControlPassword: shell.exec(`${this.tor_path} --quiet --hash-password "${this.control_password}"`, { async: false, silent: true }).stdout.trim()
|
HashedControlPassword: shell.exec(`${this.tor_path} --quiet --hash-password "${this.control_password}"`, { async: false, silent: true }).stdout.trim()
|
||||||
};
|
};
|
||||||
|
|
||||||
let config = _.extend(_.extend({}, this.tor_config), options);
|
let config = _.extend(_.extend({}, this.tor_config), options);
|
||||||
let text = Object.keys(config).map((key) => `${key} ${config[key]}`).join(os.EOL);
|
let text = Object.keys(config).map((key) => `${key} ${config[key]}`).join(os.EOL);
|
||||||
|
|
||||||
let configFilePath = await temp.openAsync('tor-router').path;
|
let configFile = await temp.openAsync('tor-router');
|
||||||
fs.writeFileAsync(configFilePath, text);
|
let configPath = configFile.path;
|
||||||
|
fs.writeFileAsync(configPath, text);
|
||||||
|
|
||||||
let tor = spawn(this.tor_path, ['-f', context.configPath], {
|
let tor = spawn(this.tor_path, ['-f', configPath], {
|
||||||
stdio: ['ignore', 'pipe', 'pipe'],
|
stdio: ['ignore', 'pipe', 'pipe'],
|
||||||
detached: false
|
detached: false
|
||||||
});
|
});
|
||||||
|
@ -121,7 +122,7 @@ class TorProcess extends EventEmitter {
|
||||||
tor.on('close', (code) => {
|
tor.on('close', (code) => {
|
||||||
this.emit('process_exit', code);
|
this.emit('process_exit', code);
|
||||||
if (this.definition && !this.definition.Name) {
|
if (this.definition && !this.definition.Name) {
|
||||||
del.sync(this.tor_config.DataDirectory, { force: true });
|
del(this.tor_config.DataDirectory, { force: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
254
src/launch.js
254
src/launch.js
|
@ -1,21 +1,16 @@
|
||||||
var nconf = require('nconf');
|
const fs = require('fs');
|
||||||
var yargs = require('yargs');
|
|
||||||
var fs = require('fs');
|
|
||||||
var TorRouter = require('../');
|
|
||||||
var SOCKSServer = TorRouter.SOCKSServer;
|
|
||||||
var DNSServer = TorRouter.DNSServer;
|
|
||||||
var TorPool = TorRouter.TorPool;
|
|
||||||
var ControlServer = TorRouter.ControlServer;
|
|
||||||
var winston = require('winston');
|
|
||||||
var async = require('async');
|
|
||||||
|
|
||||||
process.title = 'tor-router';
|
const nconf = require('nconf');
|
||||||
|
const yargs = require('yargs');
|
||||||
|
const winston = require('winston')
|
||||||
|
const Promise = require('bluebird');
|
||||||
|
|
||||||
let package_json = JSON.parse(fs.readFileSync(`${__dirname}/../package.json`, 'utf8'));
|
const { ControlServer } = require('./');
|
||||||
|
|
||||||
function main(nconf, logger) {
|
const package_json = JSON.parse(fs.readFileSync(`${__dirname}/../package.json`, 'utf8'));
|
||||||
|
|
||||||
|
async function main(nconf, logger) {
|
||||||
let instances = nconf.get('instances');
|
let instances = nconf.get('instances');
|
||||||
let log_level = logLevel;
|
|
||||||
let socks_port = nconf.get('socksPort');
|
let socks_port = nconf.get('socksPort');
|
||||||
let dns_port = nconf.get('dnsPort');
|
let dns_port = nconf.get('dnsPort');
|
||||||
let http_port = nconf.get('httpPort');
|
let http_port = nconf.get('httpPort');
|
||||||
|
@ -28,124 +23,137 @@ function main(nconf, logger) {
|
||||||
|
|
||||||
let control = new ControlServer(logger, nconf);
|
let control = new ControlServer(logger, nconf);
|
||||||
|
|
||||||
process.on('SIGHUP', () => {
|
try {
|
||||||
control.torPool.new_ips();
|
|
||||||
|
if (socks_port) {
|
||||||
|
if (typeof(socks_port) === 'boolean') {
|
||||||
|
socks_port = 9050;
|
||||||
|
nconf.set('socksPort', socks_port);
|
||||||
|
}
|
||||||
|
control.createSOCKSServer(socks_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (http_port) {
|
||||||
|
if (typeof(http_port) === 'boolean') {
|
||||||
|
http_port = 9080;
|
||||||
|
nconf.set('httpPort', http_port);
|
||||||
|
}
|
||||||
|
control.createHTTPServer(http_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dns_port) {
|
||||||
|
if (typeof(dns_port) === 'boolean') {
|
||||||
|
dns_port = 9053;
|
||||||
|
nconf.set('dnsPort', dns_port);
|
||||||
|
}
|
||||||
|
control.createDNSServer(dns_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instances) {
|
||||||
|
logger.info(`[tor]: starting ${Array.isArray(instances) ? instances.length : instances} tor instances...`)
|
||||||
|
await control.torPool.create(instances);
|
||||||
|
|
||||||
|
logger.info('[tor]: tor started');
|
||||||
|
}
|
||||||
|
|
||||||
|
await control.listen(control_port);
|
||||||
|
logger.info(`[control]: control Server listening on ${control_port}`);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`[global]: error starting application: ${error.stack}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cleanUp = (async (error) => {
|
||||||
|
let thereWasAnExitError = false;
|
||||||
|
let { handleError } = this;
|
||||||
|
try {
|
||||||
|
await Promise.all(control.torPool.instances.map((instance) => instance.exit()));
|
||||||
|
} catch (exitError) {
|
||||||
|
logger.error(`[global]: error closing tor instances: ${exitError.message}`);
|
||||||
|
thereWasAnExitError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handleError && error) {
|
||||||
|
console.log(error)
|
||||||
|
logger.error(`[global]: error shutting down: ${error.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.exit(Number(Boolean(error || thereWasAnExitError)));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (socks_port) {
|
process.title = 'tor-router';
|
||||||
if (typeof(socks_port) === 'boolean') {
|
|
||||||
socks_port = 9050;
|
|
||||||
nconf.set('socksPort', socks_port);
|
|
||||||
}
|
|
||||||
control.createSOCKSServer(socks_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (http_port) {
|
process.on('SIGHUP', () => {
|
||||||
if (typeof(http_port) === 'boolean') {
|
control.torPool.new_identites();
|
||||||
http_port = 9080;
|
});
|
||||||
nconf.set('httpPort', http_port);
|
|
||||||
}
|
|
||||||
control.createHTTPServer(http_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dns_port) {
|
|
||||||
if (typeof(dns_port) === 'boolean') {
|
|
||||||
dns_port = 9053;
|
|
||||||
nconf.set('dnsPort', dns_port);
|
|
||||||
}
|
|
||||||
control.createDNSServer(dns_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instances) {
|
|
||||||
logger.info(`[tor]: starting ${Array.isArray(instances) ? instances.length : instances} tor instances...`)
|
|
||||||
control.torPool.create(instances, (err) => {
|
|
||||||
logger.info('[tor]: tor started');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
control.listen(control_port, () => {
|
|
||||||
logger.info(`[control]: Control Server listening on ${control_port}`);
|
|
||||||
})
|
|
||||||
|
|
||||||
function cleanUp(error) {
|
|
||||||
async.each(control.torPool.instances, (instance, next) => {
|
|
||||||
instance.exit(next);
|
|
||||||
}, (exitError) => {
|
|
||||||
if (error) {
|
|
||||||
console.error(error.stack);
|
|
||||||
}
|
|
||||||
if (exitError){
|
|
||||||
console.error(exitError);
|
|
||||||
}
|
|
||||||
process.exit(Number(Boolean(error || exitError)));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
process.on('exit', cleanUp);
|
process.on('exit', cleanUp);
|
||||||
process.on('SIGINT', cleanUp);
|
process.on('SIGINT', cleanUp);
|
||||||
process.on('uncaughtException', cleanUp);
|
process.on('uncaughtException', cleanUp.bind({ handleError: true }));
|
||||||
}
|
}
|
||||||
|
|
||||||
let argv_config = require('yargs')
|
let argv_config =
|
||||||
.version(package_json.version)
|
yargs
|
||||||
.usage('Usage: tor-router [arguments]')
|
.version(package_json.version)
|
||||||
.options({
|
.usage('Usage: tor-router [arguments]')
|
||||||
f: {
|
.options({
|
||||||
alias: 'config',
|
f: {
|
||||||
describe: 'Path to a config file to use',
|
alias: 'config',
|
||||||
demand: false
|
describe: 'Path to a config file to use',
|
||||||
},
|
demand: false
|
||||||
c: {
|
},
|
||||||
alias: 'controlPort',
|
c: {
|
||||||
describe: 'Port the control server will bind to [default: 9077]',
|
alias: 'controlPort',
|
||||||
demand: false
|
describe: 'Port the control server will bind to [default: 9077]',
|
||||||
// ,default: 9077
|
demand: false
|
||||||
},
|
// ,default: 9077
|
||||||
j: {
|
},
|
||||||
alias: 'instances',
|
j: {
|
||||||
describe: 'Number of instances using the default config',
|
alias: 'instances',
|
||||||
demand: false
|
describe: 'Number of instances using the default config',
|
||||||
// ,default: 1
|
demand: false
|
||||||
},
|
// ,default: 1
|
||||||
s: {
|
},
|
||||||
alias: 'socksPort',
|
s: {
|
||||||
describe: 'Port the SOCKS5 Proxy server will bind to',
|
alias: 'socksPort',
|
||||||
demand: false,
|
describe: 'Port the SOCKS5 Proxy server will bind to',
|
||||||
// ,default: 9050
|
demand: false,
|
||||||
},
|
// ,default: 9050
|
||||||
d: {
|
},
|
||||||
alias: 'dnsPort',
|
d: {
|
||||||
describe: 'Port the DNS Proxy server will bind to',
|
alias: 'dnsPort',
|
||||||
demand: false
|
describe: 'Port the DNS Proxy server will bind to',
|
||||||
},
|
demand: false
|
||||||
h: {
|
},
|
||||||
alias: 'httpPort',
|
h: {
|
||||||
describe: 'Port the HTTP Proxy server will bind to',
|
alias: 'httpPort',
|
||||||
demand: false
|
describe: 'Port the HTTP Proxy server will bind to',
|
||||||
},
|
demand: false
|
||||||
l: {
|
},
|
||||||
alias: 'logLevel',
|
l: {
|
||||||
describe: 'Controls the verbosity of console log output. Default level is "info". Set to "verbose" to see all network traffic logged or "null" to disable logging completely [default: info]',
|
alias: 'logLevel',
|
||||||
demand: false
|
describe: 'Controls the verbosity of console log output. Default level is "info". Set to "verbose" to see all network traffic logged or "null" to disable logging completely [default: info]',
|
||||||
// ,default: "info"
|
demand: false
|
||||||
},
|
// ,default: "info"
|
||||||
p: {
|
},
|
||||||
alias: 'parentDataDirectory',
|
p: {
|
||||||
describe: 'Parent directory that will contain the data directories for the instances',
|
alias: 'parentDataDirectory',
|
||||||
demand: false
|
describe: 'Parent directory that will contain the data directories for the instances',
|
||||||
},
|
demand: false
|
||||||
b: {
|
},
|
||||||
alias: "loadBalanceMethod",
|
b: {
|
||||||
describe: 'Method that will be used to sort the instances between each request. Currently supports "round_robin" and "weighted". [default: round_robin]',
|
alias: "loadBalanceMethod",
|
||||||
demand: false
|
describe: 'Method that will be used to sort the instances between each request. Currently supports "round_robin" and "weighted". [default: round_robin]',
|
||||||
},
|
demand: false
|
||||||
t: {
|
},
|
||||||
alias: "torPath",
|
t: {
|
||||||
describe: "Provide the path for the Tor executable that will be used",
|
alias: "torPath",
|
||||||
demand: false
|
describe: "Provide the path for the Tor executable that will be used",
|
||||||
}
|
demand: false
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
nconf = require(`${__dirname}/../src/nconf_load_env.js`)(nconf);
|
require(`${__dirname}/../src/nconf_load_env.js`)(nconf);
|
||||||
nconf
|
nconf
|
||||||
.argv(argv_config);
|
.argv(argv_config);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue