Breaks the mocha test into individual files so tests can be run independently. Uses Promises in the mocha test. Adds a listen method to all servers
This commit is contained in:
parent
1c29679024
commit
b65fa27ba8
|
@ -5,4 +5,5 @@ npm-debug.log
|
|||
docker-compose.yml
|
||||
.env
|
||||
README.md
|
||||
Jenkinsfile
|
||||
.vscode
|
||||
.DS_Store
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
node_modules
|
||||
npm-debug.log
|
||||
.env
|
||||
.vscode
|
||||
.DS_Store
|
|
@ -1,4 +1,5 @@
|
|||
node_modules
|
||||
npm-debug.log
|
||||
.env
|
||||
Jenkinsfile
|
||||
.vscode
|
||||
.DS_Store
|
|
@ -2,10 +2,14 @@
|
|||
|
||||
## [4.0.0] - 2018-09-09
|
||||
|
||||
### Added
|
||||
- All servers (DNS, HTTP, SOCKS and Control) all have a `listen` method which returns a Promise that will resolve when the server is listening.
|
||||
|
||||
### Changes
|
||||
- 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
|
||||
- The mocha test has been split into individual files
|
||||
- The `Config` property of instance definitions will now inherit from `TorPool.default_tor_config`.
|
||||
- The mocha test has been split into individual files all under `test/`
|
||||
|
||||
### 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.
|
||||
|
|
|
@ -41,7 +41,7 @@ For example: `tor-router -j 3 -s 9050` would start the proxy with 3 tor instance
|
|||
|
||||
## Testing
|
||||
|
||||
Tests are written in mocha and can be found under `test/test.js` and can be run with `npm test`
|
||||
Tests are written in mocha and can be found under `test/` and can be run with `npm test`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"start": "bin/tor-router -s -d -j 1",
|
||||
"test": "mocha --exit test/index.js",
|
||||
"test": "mocha --exit test",
|
||||
"debug": "node --inspect-brk bin/tor-router"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -6,7 +6,7 @@ const rpc = require('jrpc2');
|
|||
|
||||
class ControlServer {
|
||||
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'), (() => nconf.get('torConfig')), nconf.get('parentDataDirectory'), nconf.get('loadBalanceMethod'), nconf.get('granaxOptions'), logger);
|
||||
this.logger = logger || require('./winston-silent-logger');
|
||||
this.nconf = nconf;
|
||||
|
||||
|
@ -22,9 +22,9 @@ class ControlServer {
|
|||
|
||||
server.expose('queryInstances', (async () => {
|
||||
if (!this.torPool)
|
||||
throw new Error('No instances created');
|
||||
throw new Error('No Tor Pool created');
|
||||
|
||||
this.torPool.instances.map(instance_info);
|
||||
return this.torPool.instances.map(instance_info);
|
||||
}).bind(this));
|
||||
|
||||
server.expose('queryInstanceByName', (async (instance_name) => {
|
||||
|
@ -36,7 +36,7 @@ class ControlServer {
|
|||
if (!instance)
|
||||
throw new Error(`Instance "${instance_name}"" does not exist`);
|
||||
|
||||
return instance_info(i)
|
||||
return instance_info(instance);
|
||||
}).bind(this));
|
||||
|
||||
server.expose('queryInstanceAt', (async (index) => {
|
||||
|
@ -51,9 +51,17 @@ class ControlServer {
|
|||
return instance_info(this.torPool.instance_at(index));
|
||||
}).bind(this));
|
||||
|
||||
server.expose('createInstances', this.torPool.create.bind(this.torPool));
|
||||
server.expose('createInstances', (async (num) => {
|
||||
let instances = await this.torPool.create(num);
|
||||
|
||||
server.expose('addInstances', this.torPool.add.bind(this.torPool));
|
||||
return instances.map(instance_info);
|
||||
}).bind(this));
|
||||
|
||||
server.expose('addInstances', (async (defs) => {
|
||||
let instances = await this.torPool.create(defs);
|
||||
|
||||
return instances.map(instance_info);
|
||||
}).bind(this));
|
||||
|
||||
server.expose('removeInstances', this.torPool.remove.bind(this.torPool));
|
||||
|
||||
|
@ -67,7 +75,7 @@ class ControlServer {
|
|||
|
||||
server.expose('newIdentityByName', this.torPool.new_identity_by_name.bind(this.torPool));
|
||||
|
||||
server.expose('nextInstance', (async () => this.torPool.next()).bind(this));
|
||||
server.expose('nextInstance', (async () => instance_info( await this.torPool.next() )).bind(this));
|
||||
|
||||
server.expose('closeInstances', (async () => this.torPool.exit()).bind(this));
|
||||
|
||||
|
@ -81,7 +89,7 @@ class ControlServer {
|
|||
|
||||
server.expose('setTorConfig', (async (config) => {
|
||||
await Promise.all(Object.keys(config).map((key) => {
|
||||
var value = config[key];
|
||||
let value = config[key];
|
||||
|
||||
return this.torPool.set_config_all(key, value);
|
||||
}));
|
||||
|
@ -124,23 +132,23 @@ class ControlServer {
|
|||
return this.torPool;
|
||||
}
|
||||
|
||||
createSOCKSServer(port) {
|
||||
async createSOCKSServer(port) {
|
||||
this.socksServer = new SOCKSServer(this.torPool, this.logger);
|
||||
this.socksServer.listen(port || 9050);
|
||||
await this.socksServer.listen(port || 9050);
|
||||
this.logger.info(`[socks]: Listening on ${port}`);
|
||||
this.socksServer;
|
||||
}
|
||||
|
||||
createHTTPServer(port) {
|
||||
async createHTTPServer(port) {
|
||||
this.httpServer = new HTTPServer(this.torPool, this.logger);
|
||||
this.httpServer.listen(port || 9080);
|
||||
await this.httpServer.listen(port || 9080);
|
||||
this.logger.info(`[http]: Listening on ${port}`);
|
||||
this.httpServer;
|
||||
}
|
||||
|
||||
createDNSServer(port) {
|
||||
async createDNSServer(port) {
|
||||
this.dnsServer = new DNSServer(this.torPool, this.nconf.get('dns:options'), this.nconf.get('dns:timeout'), this.logger);
|
||||
this.dnsServer.serve(port || 9053);
|
||||
await this.dnsServer.serve(port || 9053);
|
||||
this.logger.info(`[dns]: Listening on ${port}`);
|
||||
this.dnsServer;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,29 @@
|
|||
const dns = require('native-dns');
|
||||
const { UDPServer } = require('native-dns');
|
||||
const Promise = require('bluebird');
|
||||
|
||||
class DNSServer extends UDPServer {
|
||||
async listen() {
|
||||
let args = Array.from(arguments);
|
||||
let inner_func = super.serve;
|
||||
|
||||
if (!args[1])
|
||||
args[1] = null;
|
||||
|
||||
return await new Promise((resolve, reject) => {
|
||||
args.push(() => {
|
||||
let args = Array.from(arguments);
|
||||
resolve.apply(args);
|
||||
});
|
||||
|
||||
try {
|
||||
inner_func.apply(this, args);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
constructor(tor_pool, dns_options, dns_timeout, logger) {
|
||||
super(dns_options);
|
||||
this.logger = logger || require('./winston-silent-logger');
|
||||
|
|
|
@ -2,12 +2,25 @@ const http = require('http');
|
|||
const URL = require('url');
|
||||
const { Server } = http;
|
||||
|
||||
const Promise = require('bluebird');
|
||||
const socks = require('socksv5');
|
||||
const SocksProxyAgent = require('socks-proxy-agent');
|
||||
|
||||
const TOR_ROUTER_PROXY_AGENT = 'tor-router';
|
||||
|
||||
class HTTPServer extends Server {
|
||||
async listen() {
|
||||
return await new Promise((resolve, reject) => {
|
||||
let args = Array.from(arguments);
|
||||
let inner_func = super.listen;
|
||||
args.push(() => {
|
||||
let args = Array.from(arguments);
|
||||
resolve.apply(args);
|
||||
});
|
||||
inner_func.apply(this, args);
|
||||
});
|
||||
}
|
||||
|
||||
constructor(tor_pool, logger) {
|
||||
let handle_http_connections = (req, res) => {
|
||||
let url = URL.parse(req.url);
|
||||
|
@ -26,12 +39,12 @@ class HTTPServer extends Server {
|
|||
req.on('data', onIncomingData);
|
||||
req.on('end', preConnectClosed);
|
||||
req.on('error', function (err) {
|
||||
logger.error("[http-proxy]: an error occured: "+err.message);
|
||||
this.logger.error("[http-proxy]: an error occured: "+err.message);
|
||||
});
|
||||
|
||||
let connect = (tor_instance) => {
|
||||
let socks_port = tor_instance.socks_port;
|
||||
logger.verbose(`[http-proxy]: ${req.connection.remoteAddress}:${req.connection.remotePort} → 127.0.0.1:${socks_port} → ${url.hostname}:${url.port}`);
|
||||
this.logger.verbose(`[http-proxy]: ${req.connection.remoteAddress}:${req.connection.remotePort} → 127.0.0.1:${socks_port} → ${url.hostname}:${url.port}`);
|
||||
|
||||
let proxy_req = http.request({
|
||||
method: req.method,
|
||||
|
@ -74,7 +87,7 @@ class HTTPServer extends Server {
|
|||
if (tor_pool.instances.length) {
|
||||
connect(tor_pool.next());
|
||||
} else {
|
||||
logger.debug(`[http-proxy]: a connection has been attempted, but no tor instances are live... waiting for an instance to come online`);
|
||||
this.logger.debug(`[http-proxy]: a connection has been attempted, but no tor instances are live... waiting for an instance to come online`);
|
||||
tor_pool.once('instance_created', connect);
|
||||
}
|
||||
};
|
||||
|
@ -85,7 +98,7 @@ class HTTPServer extends Server {
|
|||
|
||||
let connect = (tor_instance) => {
|
||||
let socks_port = tor_instance.socks_port;
|
||||
logger && logger.verbose(`[http-connect]: ${req.connection.remoteAddress}:${req.connection.remotePort} → 127.0.0.1:${socks_port}${tor_instance.definition.Name ? ' ('+tor_instance.definition.Name+')' : '' } → ${hostname}:${port}`)
|
||||
this.logger && this.logger.verbose(`[http-connect]: ${req.connection.remoteAddress}:${req.connection.remotePort} → 127.0.0.1:${socks_port}${tor_instance.definition.Name ? ' ('+tor_instance.definition.Name+')' : '' } → ${hostname}:${port}`)
|
||||
var outbound_socket;
|
||||
|
||||
let onClose = (error) => {
|
||||
|
@ -125,7 +138,7 @@ class HTTPServer extends Server {
|
|||
if (tor_pool.instances.length) {
|
||||
connect(tor_pool.next());
|
||||
} else {
|
||||
logger.debug(`[http-connect]: a connection has been attempted, but no tor instances are live... waiting for an instance to come online`);
|
||||
this.logger.debug(`[http-connect]: a connection has been attempted, but no tor instances are live... waiting for an instance to come online`);
|
||||
tor_pool.once('instance_created', connect);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
const socks = require('socksv5');
|
||||
const Promise = require('bluebird');
|
||||
const { Server } = socks;
|
||||
|
||||
class SOCKSServer extends Server{
|
||||
async listen() {
|
||||
return await new Promise((resolve, reject) => {
|
||||
let args = Array.from(arguments);
|
||||
let inner_func = super.listen;
|
||||
args.push(() => {
|
||||
let args = Array.from(arguments);
|
||||
resolve.apply(args);
|
||||
});
|
||||
inner_func.apply(this, args);
|
||||
});
|
||||
}
|
||||
|
||||
constructor(tor_pool, logger) {
|
||||
let handleConnection = (info, accept, deny) => {
|
||||
let inbound_socket = accept(true);
|
||||
|
@ -28,7 +41,7 @@ class SOCKSServer extends Server{
|
|||
|
||||
let connect = (tor_instance) => {
|
||||
let socks_port = tor_instance.socks_port;
|
||||
logger.verbose(`[socks]: ${info.srcAddr}:${info.srcPort} → 127.0.0.1:${socks_port}${tor_instance.definition.Name ? ' ('+tor_instance.definition.Name+')' : '' } → ${info.dstAddr}:${info.dstPort}`)
|
||||
this.logger.verbose(`[socks]: ${info.srcAddr}:${info.srcPort} → 127.0.0.1:${socks_port}${tor_instance.definition.Name ? ' ('+tor_instance.definition.Name+')' : '' } → ${info.dstAddr}:${info.dstPort}`)
|
||||
|
||||
socks.connect({
|
||||
host: info.dstAddr,
|
||||
|
@ -60,7 +73,7 @@ class SOCKSServer extends Server{
|
|||
if (tor_pool.instances.length) {
|
||||
connect(tor_pool.next());
|
||||
} else {
|
||||
logger.debug(`[socks]: a connection has been attempted, but no tor instances are live... waiting for an instance to come online`);
|
||||
this.logger.debug(`[socks]: a connection has been attempted, but no tor instances are live... waiting for an instance to come online`);
|
||||
tor_pool.once('instance_created', connect);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -29,20 +29,33 @@ const WeightedList = require('js-weighted-list');
|
|||
|
||||
const TorProcess = require('./TorProcess');
|
||||
|
||||
Promise.promisifyAll(fs);
|
||||
|
||||
class TorPool extends EventEmitter {
|
||||
constructor(tor_path, default_config, data_directory, load_balance_method, granax_options, logger) {
|
||||
if (!data_directory)
|
||||
throw new Error('Invalid "data_directory"');
|
||||
super();
|
||||
this._instances = [];
|
||||
default_config = _.extend({}, (default_config || {}));
|
||||
this.default_tor_config = default_config;
|
||||
this._default_tor_config = default_config;
|
||||
this.data_directory = data_directory;
|
||||
this.load_balance_method = load_balance_method;
|
||||
!fs.existsSync(this.data_directory) && fs.mkdirSync(this.data_directory);
|
||||
this.tor_path = tor_path;
|
||||
this.logger = logger || require('./winston-silent-logger');
|
||||
this.granax_options = granax_options;
|
||||
}
|
||||
|
||||
get default_tor_config() {
|
||||
if (typeof(this._default_tor_config) === 'function')
|
||||
return this._default_tor_config();
|
||||
else if (this._default_tor_config)
|
||||
return _.cloneDeep(this._default_tor_config);
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
set default_tor_config(value) { this._default_tor_config = value; }
|
||||
|
||||
static get load_balance_methods() {
|
||||
return {
|
||||
round_robin: function (instances) {
|
||||
|
@ -68,9 +81,11 @@ class TorPool extends EventEmitter {
|
|||
}
|
||||
|
||||
async create_instance(instance_definition) {
|
||||
if (!(fs.existsSync(this.data_directory)))
|
||||
await fs.mkdirAsync(this.data_directory);
|
||||
|
||||
this._instances._weighted_list = void(0);
|
||||
if (!instance_definition.Config)
|
||||
instance_definition.Config = _.extend({}, this.default_tor_config);
|
||||
instance_definition.Config = _.extend(_.cloneDeep(this.default_tor_config), (instance_definition.Config || {}));
|
||||
let instance_id = nanoid();
|
||||
instance_definition.Config.DataDirectory = instance_definition.Config.DataDirectory || path.join(this.data_directory, (instance_definition.Name || instance_id));
|
||||
|
||||
|
@ -138,7 +153,7 @@ class TorPool extends EventEmitter {
|
|||
}
|
||||
|
||||
next() {
|
||||
this._instances = load_balance_methods[this.load_balance_method](this._instances);
|
||||
this._instances = TorPool.load_balance_methods[this.load_balance_method](this._instances);
|
||||
return this.instances[0];
|
||||
}
|
||||
|
||||
|
@ -148,7 +163,7 @@ class TorPool extends EventEmitter {
|
|||
}
|
||||
|
||||
async new_identites() {
|
||||
await Promise.all(this.instances.map((instance) => instance.new_identity(next)));
|
||||
await Promise.all(this.instances.map((instance) => instance.new_identity()));
|
||||
}
|
||||
|
||||
async new_identity_at(index) {
|
||||
|
@ -201,7 +216,7 @@ class TorPool extends EventEmitter {
|
|||
}
|
||||
|
||||
async signal_all(signal) {
|
||||
await Promise.all(this.instances.map((instance) => instance.signal(signal, next)));
|
||||
await Promise.all(this.instances.map((instance) => instance.signal(signal)));
|
||||
}
|
||||
|
||||
async signal_by_name(name, signal) {
|
||||
|
|
|
@ -112,7 +112,7 @@ class TorProcess extends EventEmitter {
|
|||
|
||||
let configFile = await temp.openAsync('tor-router');
|
||||
let configPath = configFile.path;
|
||||
fs.writeFileAsync(configPath, text);
|
||||
await fs.writeFileAsync(configPath, text);
|
||||
|
||||
let tor = spawn(this.tor_path, ['-f', configPath], {
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
|
|
|
@ -24,6 +24,7 @@ async function main(nconf, logger) {
|
|||
let control = new ControlServer(logger, nconf);
|
||||
|
||||
try {
|
||||
await control.listen(control_port);
|
||||
|
||||
if (socks_port) {
|
||||
if (typeof(socks_port) === 'boolean') {
|
||||
|
@ -50,13 +51,11 @@ async function main(nconf, logger) {
|
|||
}
|
||||
|
||||
if (instances) {
|
||||
logger.info(`[tor]: starting ${Array.isArray(instances) ? instances.length : instances} tor instances...`)
|
||||
logger.info(`[tor]: starting ${Array.isArray(instances) ? instances.length : instances} tor instance(s)...`)
|
||||
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}`);
|
||||
|
@ -160,6 +159,8 @@ nconf
|
|||
let nconf_config = nconf.get('config');
|
||||
if (nconf_config) {
|
||||
nconf.file(nconf_config);
|
||||
} else {
|
||||
nconf.use('memory');
|
||||
}
|
||||
|
||||
nconf.defaults(require(`${__dirname}/../src/default_config.js`));
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
|
||||
const _ = require('lodash');
|
||||
const assert = require('chai').assert;
|
||||
const rpc = require('jrpc2');
|
||||
const Promise = require('bluebird');
|
||||
const nconf = require('nconf');
|
||||
const getPort = require('get-port');
|
||||
|
||||
const logger = require('../src/winston-silent-logger');
|
||||
|
||||
nconf.use('memory');
|
||||
require(`${__dirname}/../src/nconf_load_env.js`)(nconf);
|
||||
nconf.defaults(require(`${__dirname}/../src/default_config.js`));
|
||||
const { ControlServer } = require('../');
|
||||
const { ControlServer, TorPool, HTTPServer, SOCKSServer, DNSServer } = require('../');
|
||||
|
||||
let controlServer = new ControlServer(logger, nconf);
|
||||
let controlServer = new ControlServer(null, nconf);
|
||||
let controlPort;
|
||||
|
||||
describe('ControlServer', function () {
|
||||
describe('#listen(port)', function () {
|
||||
it('should bind to a given port', async function () {
|
||||
|
@ -24,7 +23,7 @@ describe('ControlServer', function () {
|
|||
it('should create a TorPool with a given configuration', function () {
|
||||
let torPool = controlServer.createTorPool({ ProtocolWarnings: 1 });
|
||||
|
||||
assert.ok((controlServer.torPool instanceof (TorRouter.TorPool)));
|
||||
assert.instanceOf(controlServer.torPool, TorPool);
|
||||
assert.equal(1, torPool.default_tor_config.ProtocolWarnings);
|
||||
});
|
||||
});
|
||||
|
@ -60,5 +59,3 @@ describe('ControlServer', function () {
|
|||
await controlServer.torPool.exit();
|
||||
});
|
||||
});
|
||||
|
||||
require('./RPCServer');
|
|
@ -3,15 +3,18 @@ const nconf = require('nconf');
|
|||
const getPort = require('get-port');
|
||||
const dns = require('native-dns');
|
||||
|
||||
const logger = require('../src/winston-silent-logger');
|
||||
const { TorPool, DNSServer } = require('../');
|
||||
const { WAIT_FOR_CREATE } = require('./constants');
|
||||
|
||||
nconf.use('memory');
|
||||
require(`${__dirname}/../src/nconf_load_env.js`)(nconf);
|
||||
nconf.defaults(require(`${__dirname}/../src/default_config.js`));
|
||||
|
||||
let dnsServerTorPool;
|
||||
let dnsServer;
|
||||
describe('DNSServer', function () {
|
||||
dnsServerTorPool = new TorPool(nconf.get('torPath'), {}, nconf.get('parentDataDirectory'), 'round_robin', null, logger);
|
||||
dnsServer = new DNSServer(dnsServerTorPool, {}, 10000, logger);
|
||||
dnsServerTorPool = new TorPool(nconf.get('torPath'), {}, nconf.get('parentDataDirectory'), 'round_robin', null);
|
||||
dnsServer = new DNSServer(dnsServerTorPool, {}, 10000);
|
||||
let dnsPort;
|
||||
before('start up server', async function (){
|
||||
this.timeout(WAIT_FOR_CREATE);
|
||||
|
@ -19,7 +22,7 @@ describe('DNSServer', function () {
|
|||
await dnsServerTorPool.create(1);
|
||||
dnsPort = await getPort();
|
||||
|
||||
dnsServer.serve(dnsPort);
|
||||
await dnsServer.listen(dnsPort);
|
||||
});
|
||||
|
||||
describe('#handle_dns_request(req, res)', function () {
|
||||
|
@ -32,7 +35,7 @@ describe('DNSServer', function () {
|
|||
type: 'A'
|
||||
}),
|
||||
server: { address: '127.0.0.1', port: dnsPort, type: 'udp' },
|
||||
timeout: 1000,
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
req.on('timeout', function () {
|
||||
|
|
|
@ -3,18 +3,18 @@ const request = require('request-promise');
|
|||
const getPort = require('get-port');
|
||||
const ProxyAgent = require('proxy-agent');
|
||||
|
||||
const logger = require('../src/winston-silent-logger');
|
||||
const { TorPool, HTTPServer } = require('../');
|
||||
const { WAIT_FOR_CREATE, PAGE_LOAD_TIME } = require('./constants');
|
||||
|
||||
nconf.use('memory');
|
||||
require(`${__dirname}/../src/nconf_load_env.js`)(nconf);
|
||||
nconf.defaults(require(`${__dirname}/../src/default_config.js`));
|
||||
|
||||
let httpServerTorPool;
|
||||
let httpServer;
|
||||
describe('HTTPServer', function () {
|
||||
httpServerTorPool = new TorPool(nconf.get('torPath'), {}, nconf.get('parentDataDirectory'), 'round_robin', null, logger);
|
||||
httpServer = new HTTPServer(httpServerTorPool, logger);
|
||||
httpServerTorPool = new TorPool(nconf.get('torPath'), {}, nconf.get('parentDataDirectory'), 'round_robin', null);
|
||||
httpServer = new HTTPServer(httpServerTorPool);
|
||||
let httpPort;
|
||||
before('start up server', async function (){
|
||||
this.timeout(WAIT_FOR_CREATE);
|
||||
|
@ -22,7 +22,7 @@ describe('HTTPServer', function () {
|
|||
await httpServerTorPool.create(1);
|
||||
httpPort = await getPort();
|
||||
|
||||
httpServer.listen(httpPort);
|
||||
await httpServer.listen(httpPort);
|
||||
});
|
||||
|
||||
describe('#handle_http_connections(req, res)', function () {
|
||||
|
@ -31,7 +31,7 @@ describe('HTTPServer', function () {
|
|||
|
||||
await request({
|
||||
url: 'http://example.com',
|
||||
agent: new ProxyAgent(`http://localhost:${httpPort}`)
|
||||
agent: new ProxyAgent(`http://127.0.0.1:${httpPort}`)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -42,7 +42,7 @@ describe('HTTPServer', function () {
|
|||
|
||||
await request({
|
||||
url: 'https://example.com',
|
||||
agent: new ProxyAgent(`http://localhost:${httpPort}`)
|
||||
agent: new ProxyAgent(`http://127.0.0.1:${httpPort}`)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
|
||||
const _ = require('lodash');
|
||||
const assert = require('chai').assert;
|
||||
const rpc = require('jrpc2');
|
||||
const Promise = require('bluebird');
|
||||
const nconf = require('nconf');
|
||||
const rpc = require('jrpc2');
|
||||
const getPort = require('get-port');
|
||||
|
||||
const logger = require('../src/winston-silent-logger');
|
||||
|
||||
nconf.use('memory');
|
||||
require(`${__dirname}/../src/nconf_load_env.js`)(nconf);
|
||||
nconf.defaults(require(`${__dirname}/../src/default_config.js`));
|
||||
const { ControlServer } = require('../');
|
||||
const { WAIT_FOR_CREATE } = require('./constants');
|
||||
|
||||
let rpcControlServer = new ControlServer(logger, nconf);
|
||||
let rpcControlServer = new ControlServer(null, nconf);
|
||||
let rpcControlPort;
|
||||
let rpcClient;
|
||||
describe('ControlServer - RPC', function () {
|
||||
describe('ControlServer - RPC Interface', function () {
|
||||
before('setup control server', async function () {
|
||||
rpcControlPort = await getPort();
|
||||
await rpcControlServer.listen(rpcControlPort);
|
||||
|
@ -35,11 +35,11 @@ describe('ControlServer - RPC', function () {
|
|||
it('should return a list of instances', async function () {
|
||||
let raw = await rpcClient.invokeAsync('queryInstances', []);
|
||||
|
||||
var instances = JSON.parse(raw).result;
|
||||
let instances = JSON.parse(raw).result;
|
||||
|
||||
assert.isArray(instances, 'Did not return an array');
|
||||
assert.isNotEmpty(instances);
|
||||
assert.isTrue(instances.every((instance) => ( typeof(instance.name) !== 'undefined' ) && ( instance.name !== null )));
|
||||
assert.isNotEmpty(instances, 'Returned an empty array');
|
||||
assert.isTrue(instances.every((instance) => ( typeof(instance.name) !== 'undefined' ) && ( instance.name !== null )), 'Objects were not valid');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -62,7 +62,7 @@ describe('ControlServer - RPC', function () {
|
|||
it('should return a single instance by name', async function () {
|
||||
let raw = await rpcClient.invokeAsync('queryInstanceByName', ['instance-1']);
|
||||
|
||||
var instance = JSON.parse(raw).result;
|
||||
let instance = JSON.parse(raw).result;
|
||||
|
||||
assert.isOk(instance);
|
||||
});
|
||||
|
@ -73,7 +73,7 @@ describe('ControlServer - RPC', function () {
|
|||
it('should return a single instance by index', async function () {
|
||||
let raw = await rpcClient.invokeAsync('queryInstanceAt', [0]);
|
||||
|
||||
var instance = JSON.parse(raw).result;
|
||||
let instance = JSON.parse(raw).result;
|
||||
|
||||
assert.isOk(instance);
|
||||
});
|
||||
|
@ -132,9 +132,10 @@ describe('ControlServer - RPC', function () {
|
|||
this.timeout(WAIT_FOR_CREATE);
|
||||
|
||||
await rpcControlServer.torPool.create_instance({ Name: 'config-test' });
|
||||
let value = await rpcControlServer.torPool.instance_by_name('config-test').get_config('TestSocks');
|
||||
let values = await rpcControlServer.torPool.instance_by_name('config-test').get_config('TestSocks');
|
||||
|
||||
assert.equal(value, 1);
|
||||
assert.isNotEmpty(values);
|
||||
assert.equal(values[0], "1");
|
||||
});
|
||||
|
||||
after('remove instance', async function () {
|
||||
|
@ -150,8 +151,8 @@ describe('ControlServer - RPC', function () {
|
|||
});
|
||||
|
||||
it('should return a tor config with a modified property', async function () {
|
||||
this.timeout(3000);
|
||||
let raw = await rpcClient.invokeAsync('getDefaultTorConfig', [ { } ]);
|
||||
this.timeout(6000);
|
||||
let raw = await rpcClient.invokeAsync('getDefaultTorConfig', [ ]);
|
||||
let config = JSON.parse(raw).result;
|
||||
|
||||
assert.equal(config.TestSocks, 1);
|
||||
|
@ -198,11 +199,12 @@ describe('ControlServer - RPC', function () {
|
|||
await rpcControlServer.torPool.instance_by_name('instance-1').set_config('TestSocks', 1);
|
||||
});
|
||||
|
||||
it('should retrieve the property from the tor instance', async function (done) {
|
||||
let raw = await rpcClient.invokeAsync('getInstanceConfigByName', ['instance-1']);
|
||||
let value = JSON.parse(raw).result;
|
||||
it('should retrieve the property from the tor instance', async function () {
|
||||
let raw = await rpcClient.invokeAsync('getInstanceConfigByName', ['instance-1', "TestSocks"]);
|
||||
let values = JSON.parse(raw).result;
|
||||
|
||||
assert.equal(value, 1);
|
||||
assert.isNotEmpty(values);
|
||||
assert.equal(values[0], "1");
|
||||
});
|
||||
|
||||
after('unset config property', async function () {
|
||||
|
@ -218,10 +220,11 @@ describe('ControlServer - RPC', function () {
|
|||
});
|
||||
|
||||
it('should retrieve the property from the tor instance', async function () {
|
||||
let raw = await rpcClient.invokeAsync('getInstanceConfigByName', [0]);
|
||||
let value = JSON.parse(raw).result;
|
||||
let raw = await rpcClient.invokeAsync('getInstanceConfigAt', [0, "TestSocks"]);
|
||||
let values = JSON.parse(raw).result;
|
||||
|
||||
assert.equal(value, 1);
|
||||
assert.isNotEmpty(values);
|
||||
assert.equal(values[0], "1");
|
||||
});
|
||||
|
||||
after('unset config property', async function () {
|
|
@ -3,18 +3,18 @@ const request = require('request-promise');
|
|||
const getPort = require('get-port');
|
||||
const ProxyAgent = require('proxy-agent');
|
||||
|
||||
const logger = require('../src/winston-silent-logger');
|
||||
const { TorPool, SOCKSServer } = require('../');
|
||||
const { WAIT_FOR_CREATE, PAGE_LOAD_TIME } = require('./constants');
|
||||
|
||||
nconf.use('memory');
|
||||
require(`${__dirname}/../src/nconf_load_env.js`)(nconf);
|
||||
nconf.defaults(require(`${__dirname}/../src/default_config.js`));
|
||||
|
||||
let socksServerTorPool;
|
||||
let socksServer;
|
||||
describe('SOCKSServer', function () {
|
||||
socksServerTorPool = new TorPool(nconf.get('torPath'), {}, nconf.get('parentDataDirectory'), 'round_robin', null, logger);
|
||||
socksServer = new SOCKSServer(socksServerTorPool, logger);
|
||||
socksServerTorPool = new TorPool(nconf.get('torPath'), {}, nconf.get('parentDataDirectory'), 'round_robin', null);
|
||||
socksServer = new SOCKSServer(socksServerTorPool);
|
||||
let socksPort;
|
||||
before('start up server', async function (){
|
||||
this.timeout(WAIT_FOR_CREATE);
|
||||
|
@ -22,7 +22,7 @@ describe('SOCKSServer', function () {
|
|||
await socksServerTorPool.create(1);
|
||||
socksPort = await getPort();
|
||||
|
||||
socksServer.listen(socksPort);
|
||||
await socksServer.listen(socksPort);
|
||||
});
|
||||
|
||||
describe('#handleConnection(socket)', function () {
|
||||
|
@ -31,7 +31,7 @@ describe('SOCKSServer', function () {
|
|||
|
||||
await request({
|
||||
url: 'http://example.com',
|
||||
agent: new ProxyAgent(`socks://localhost:${socksPort}`)
|
||||
agent: new ProxyAgent(`socks://127.0.0.1:${socksPort}`)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,14 +5,13 @@ const _ = require('lodash');
|
|||
|
||||
const { TorPool } = require('../');
|
||||
const { WAIT_FOR_CREATE } = require('./constants');
|
||||
const logger = require('../src/winston-silent-logger');
|
||||
|
||||
nconf.use('memory');
|
||||
require(`${__dirname}/../src/nconf_load_env.js`)(nconf);
|
||||
nconf.defaults(require(`${__dirname}/../src/default_config.js`));
|
||||
|
||||
let torPool;
|
||||
describe('TorPool', function () {
|
||||
torPool = new TorPool(nconf.get('torPath'), {}, nconf.get('parentDataDirectory'), 'round_robin', null, logger);
|
||||
const torPoolFactory = () => new TorPool(nconf.get('torPath'), {}, nconf.get('parentDataDirectory'), 'round_robin', null);
|
||||
|
||||
describe('#create_instance(instance_defintion)', function () {
|
||||
let instance_defintion = {
|
||||
|
@ -22,6 +21,9 @@ describe('TorPool', function () {
|
|||
}
|
||||
};
|
||||
|
||||
let torPool;
|
||||
before('create tor pool', () => { torPool = torPoolFactory(); })
|
||||
|
||||
it('should create one tor instance based on the provided definition', async function () {
|
||||
this.timeout(WAIT_FOR_CREATE);
|
||||
await torPool.create_instance(instance_defintion);
|
||||
|
@ -51,9 +53,12 @@ describe('TorPool', function () {
|
|||
{ Name: 'instance-2', Config: { ProtocolWarnings: 1 } }
|
||||
];
|
||||
|
||||
let torPool;
|
||||
before('create tor pool', () => { torPool = torPoolFactory(); })
|
||||
|
||||
it('should create instances from several instance definitions', async function () {
|
||||
this.timeout(WAIT_FOR_CREATE*2);
|
||||
await torPool.add(instance_defintions)
|
||||
await torPool.add(_.cloneDeep(instance_defintions))
|
||||
});
|
||||
|
||||
it('2 instances should exist in the pool', function () {
|
||||
|
@ -61,19 +66,21 @@ describe('TorPool', function () {
|
|||
});
|
||||
|
||||
it('the created instances should have the same defintion properties as the input definitions', function () {
|
||||
assert.deepEqual(instance_defintions, torPool.instances.map((instance) => {
|
||||
let live_instance_definitions = torPool.instances.map((instance) => {
|
||||
let def_clone = _.cloneDeep(instance.definition);
|
||||
delete def_clone.Config.DataDirectory;
|
||||
return def_clone;
|
||||
}).sort(function(a,b) {return (a.Name > b.Name) ? 1 : ((b.Name > a.Name) ? -1 : 0);}));
|
||||
}).sort((a,b) => (a.Name > b.Name) ? 1 : ((b.Name > a.Name) ? -1 : 0));
|
||||
|
||||
assert.deepEqual(instance_defintions, live_instance_definitions);
|
||||
});
|
||||
|
||||
it('the created instances should have the same config properties specified in the definiton', async function (done) {
|
||||
it('the created instances should have the same config properties specified in the definiton', async function () {
|
||||
this.timeout(10000);
|
||||
|
||||
let values = await Promise.all(torPool.instances.map((instance) => instance.get_config('ProtocolWarnings')));
|
||||
|
||||
assert.isTrue( values.every((value) => value === 1) );
|
||||
values = _.flatten(values);
|
||||
assert.isTrue( values.every((value) => value === "1") );
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () {
|
||||
|
@ -82,7 +89,13 @@ describe('TorPool', function () {
|
|||
});
|
||||
|
||||
describe('#create(number_of_instances)', function () {
|
||||
let torPool;
|
||||
|
||||
before('create tor pool', () => {
|
||||
torPool = torPoolFactory();
|
||||
torPool.default_tor_config = { TestSocks: 1 };
|
||||
})
|
||||
|
||||
it('should create 2 instances with the default config', async function () {
|
||||
this.timeout(WAIT_FOR_CREATE*2);
|
||||
await torPool.create(2);
|
||||
|
@ -95,19 +108,21 @@ describe('TorPool', function () {
|
|||
it('the created instances should have the same config properties specified in the default config', async function () {
|
||||
this.timeout(10000);
|
||||
|
||||
let values = await Promise.all(torPool.instances.map((instance) => instance.get_config('ProtocolWarnings')));
|
||||
|
||||
assert.isTrue( values.every((value) => value === 1) );
|
||||
let values = await Promise.all(torPool.instances.map((instance) => instance.get_config('TestSocks')));
|
||||
values = _.flatten(values);
|
||||
assert.isTrue( values.every((value) => value === "1") );
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () {
|
||||
torPool.default_tor_config = {};
|
||||
await torPool.exit(done);
|
||||
await torPool.exit();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
let torPool;
|
||||
describe('#next()', function () {
|
||||
before('create tor pool', () => { torPool = torPoolFactory(); })
|
||||
|
||||
before('create tor instances', async function () {
|
||||
this.timeout(WAIT_FOR_CREATE * 3);
|
||||
await torPool.add([
|
||||
|
@ -127,8 +142,8 @@ describe('TorPool', function () {
|
|||
});
|
||||
|
||||
it('result of next should be different if run twice', function () {
|
||||
var t1 = torPool.next().instance_name;
|
||||
var t2 = torPool.next().instance_name;
|
||||
let t1 = torPool.next().instance_name;
|
||||
let t2 = torPool.next().instance_name;
|
||||
assert.notEqual(t1, t2);
|
||||
});
|
||||
});
|
||||
|
@ -192,8 +207,8 @@ describe('TorPool', function () {
|
|||
this.timeout(5000);
|
||||
|
||||
let values = await Promise.all(torPool.instances.map((instance) => instance.get_config('TestSocks')));
|
||||
|
||||
assert.isTrue( values.every((value) => value === 1) );
|
||||
values = _.flatten(values);
|
||||
assert.isTrue( values.every((value) => value === "1") );
|
||||
});
|
||||
|
||||
after('unset config options', async function () {
|
||||
|
|
|
@ -3,13 +3,13 @@ const assert = require('chai').assert;
|
|||
|
||||
const { TorProcess } = require('../');
|
||||
const { WAIT_FOR_CREATE } = require('./constants');
|
||||
const logger = require('../src/winston-silent-logger');
|
||||
|
||||
nconf.use('memory');
|
||||
require(`${__dirname}/../src/nconf_load_env.js`)(nconf);
|
||||
nconf.defaults(require(`${__dirname}/../src/default_config.js`));
|
||||
|
||||
describe('TorProcess', function () {
|
||||
let tor = new TorProcess(nconf.get('torPath'), { DataDirectory: nconf.get('parentDataDirectory'), ProtocolWarnings: 0 }, null, logger);
|
||||
let tor = new TorProcess(nconf.get('torPath'), { DataDirectory: nconf.get('parentDataDirectory'), ProtocolWarnings: 0 }, null);
|
||||
describe('#create()', function () {
|
||||
this.timeout(WAIT_FOR_CREATE);
|
||||
|
||||
|
|
|
@ -5,4 +5,5 @@ describe("TorRouter", function () {
|
|||
require('./HTTPServer');
|
||||
require('./DNSServer');
|
||||
require('./ControlServer');
|
||||
require('./RPCInterface');
|
||||
});
|
Loading…
Reference in a new issue