Adds "queryInstanceByName" and "queryInstanceAt"

This commit is contained in:
Zachary Boyd 2018-08-10 13:06:40 -04:00
parent 58d3d1da17
commit 7d996ffa81
6 changed files with 111 additions and 51 deletions

View file

@ -1,5 +1,11 @@
# Changelog # Changelog
## [3.4.3] - 2018-08-10
### Added
- Adds a changelog
- Adds `queryInstanceByName` and `queryInstanceAt` RPC methods to retrieve individual instances
## [3.4.2] - 2018-08-09 ## [3.4.2] - 2018-08-09
### Added ### Added
@ -30,7 +36,7 @@
## [3.3.0] - 2018-05-10 ## [3.3.0] - 2018-05-10
### Added ### Added
- Adds documentation on all RPC Methods available - Adds documentation on all available RPC Methods
- Allows different load-balance methods to be defined, and changed at runtime and via RPC - Allows different load-balance methods to be defined, and changed at runtime and via RPC
- Each instance can have started with a specific configuration (torrc) by setting the `Config` property in the definition - Each instance can have started with a specific configuration (torrc) by setting the `Config` property in the definition

View file

@ -4,6 +4,8 @@
Tor Router also includes a DNS proxy server and a HTTP proxy as well, which like the SOCKS proxy will distribute traffic across multiple instances of Tor in round-robin fashion. The HTTP proxy server can be used to access Tor via an HTTP Proxy. Tor Router also includes a DNS proxy server and a HTTP proxy as well, which like the SOCKS proxy will distribute traffic across multiple instances of Tor in round-robin fashion. The HTTP proxy server can be used to access Tor via an HTTP Proxy.
A list of changes can be [found here](https://github.com/znetstar/tor-router/blob/master/CHANGELOG.md)
## Building and Running ## Building and Running
The only installation requirement is node.js. Tor is bundled with the application. To use an external Tor executable use the `--torPath` command line switch or set the `TOR_PATH` environment variable. The only installation requirement is node.js. Tor is bundled with the application. To use an external Tor executable use the `--torPath` command line switch or set the `TOR_PATH` environment variable.
@ -37,6 +39,10 @@ The following command line switches and their environment variable equivalents a
For example: `tor-router -j 3 -s 9050` would start the proxy with 3 tor instances and listen for SOCKS connections on 9050. For example: `tor-router -j 3 -s 9050` would start the proxy with 3 tor instances and listen for SOCKS connections on 9050.
## Testing
Tests are written in mocha and can be found under `test/test.js` and can be run with `npm test`
## Configuration ## Configuration
Using the `--config` or `-f` command line switch you can set the path to a JSON file which can be used to load configuration on startup Using the `--config` or `-f` command line switch you can set the path to a JSON file which can be used to load configuration on startup
@ -147,8 +153,4 @@ let rpcRequest = {
"id": 1 "id": 1
}; };
client.write(JSON.stringify(rpcRequest)); client.write(JSON.stringify(rpcRequest));
``` ```
## Test
Tests are written in mocha, just run `npm test`

View file

@ -1,14 +1,22 @@
## RPC Functions # RPC Functions
The following functions are available via the RPC The following functions are available via the RPC
# queryInstances() ## queryInstances()
Returns an array containing information on the instances currently running under the router. Returns an array containing information on the instances currently running under the router.
# createInstances(Array or Integrer) ## queryInstanceByName(String)
If passed an integrer, creates thats many Tor instances. An array can also be passed describing the names, weights and configurations of prospective instances. : Returns information on an instance identified by name
## queryInstanceAt(Integer)
Returns information on an instance identified by index
## createInstances(Array or Integer)
If passed an Integer, creates thats many Tor instances. An array can also be passed describing the names, weights and configurations of prospective instances. :
``` ```
var rpcRequest = { var rpcRequest = {
@ -30,63 +38,63 @@ var rpcRequest = {
Will wait until the Tor Instance has fully connected to the network before returning Will wait until the Tor Instance has fully connected to the network before returning
# addInstances(Array) ## addInstances(Array)
Serves the same purpose as "createInstances" but only takes an Array Serves the same purpose as "createInstances" but only takes an Array
# removeInstances(Integrer) ## removeInstances(Integer)
Removes a number of instances Removes a number of instances
# removeInstanceAt(Integrer) ## removeInstanceAt(Integer)
Remove a specific instance from the pool by its index Remove a specific instance from the pool by its index
# removeInstanceByName(String) ## removeInstanceByName(String)
Remove a specific instance from the pool by its name Remove a specific instance from the pool by its name
# newIdentites() ## newIdentites()
Get new identites for all instances Get new identites for all instances
# newIdentityAt(Integrer) ## newIdentityAt(Integer)
Get a new identity for a specific instance by its index Get a new identity for a specific instance by its index
# newIdentityByName(String) ## newIdentityByName(String)
Get a new identity for a specific instance by its name Get a new identity for a specific instance by its name
# nextInstance() ## nextInstance()
Cycle to the next instance using the load balancing method Cycle to the next instance using the load balancing method
# closeInstances() ## closeInstances()
Shutdown all Tor instances Shutdown all Tor instances
# setTorConfig(Object) ## setTorConfig(Object)
Applies the configuration to all active instances Applies the configuration to all active instances
# getDefaultTorConfig() ## getDefaultTorConfig()
Retrieve the default Tor Config for all future instances Retrieve the default Tor Config for all future instances
# setDefaultTorConfig(Object) ## setDefaultTorConfig(Object)
Set the default Tor Config for all future instances Set the default Tor Config for all future instances
# getLoadBalanceMethod() ## getLoadBalanceMethod()
Get the current load balance method Get the current load balance method
# setLoadBalanceMethod(String) ## setLoadBalanceMethod(String)
Set the current load balance method Set the current load balance method
# getInstanceConfigAt(Integrer: index, String: keyword) ## getInstanceConfigAt(Integer: index, String: keyword)
Retrieves the current value of an option set in the configuration by the index of the instance using the control protocol. Retrieves the current value of an option set in the configuration by the index of the instance using the control protocol.
@ -103,28 +111,28 @@ var rpcRequest = {
}; };
``` ```
# getInstanceConfigByName(String: name, String: keyword) ## getInstanceConfigByName(String: name, String: keyword)
Works the same way as `getInstanceConfigAt` except takes an instance name instead of an index Works the same way as `getInstanceConfigAt` except takes an instance name instead of an index
# setInstanceConfigAt(Integrer: index, String: keyword, String: value) ## setInstanceConfigAt(Integer: index, String: keyword, String: value)
Sets the value in the configuration of an instance using the control protocol. Changes will be applied immediately. Sets the value in the configuration of an instance using the control protocol. Changes will be applied immediately.
# setInstanceConfigByName(Integrer: index, String: keyword, String: value) ## setInstanceConfigByName(Integer: index, String: keyword, String: value)
Works the same way as `setInstanceConfigAt` except takes an instance name instead of an index Works the same way as `setInstanceConfigAt` except takes an instance name instead of an index
# signalAllInstances(String) ## signalAllInstances(String)
Sends a signal using the control protocol to all instances Sends a signal using the control protocol to all instances
A list of all signals can be [found here](https://gitweb.torproject.org/torspec.git/tree/control-spec.txt) A list of all signals can be [found here](https://gitweb.torproject.org/torspec.git/tree/control-spec.txt)
# signalInstanceAt(Integrer: index, String: signal) ## signalInstanceAt(Integer: index, String: signal)
Sends a signal using the control protocol to an instance identified by its index Sends a signal using the control protocol to an instance identified by its index
# signalInstanceByName(String: name, String: signal) ## signalInstanceByName(String: name, String: signal)
Sends a signal using the control protocol to an instance identified by its name Sends a signal using the control protocol to an instance identified by its name

View file

@ -1,6 +1,6 @@
{ {
"name": "tor-router", "name": "tor-router",
"version": "3.4.2", "version": "3.4.3",
"main": "src/index.js", "main": "src/index.js",
"repository": "git@github.com:znetstar/tor-router.git", "repository": "git@github.com:znetstar/tor-router.git",
"author": "Zachary Boyd <zachary@zacharyboyd.nyc>", "author": "Zachary Boyd <zachary@zacharyboyd.nyc>",

View file

@ -17,14 +17,44 @@ class ControlServer {
server.expose('createDNSServer', this.createDNSServer.bind(this)); server.expose('createDNSServer', this.createDNSServer.bind(this));
server.expose('createHTTPServer', this.createHTTPServer.bind(this)); server.expose('createHTTPServer', this.createHTTPServer.bind(this));
// queryInstanceAt, queryInstanceByName const instance_info = (i) => {
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', (function () {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!this.torPool) if (!this.torPool)
return reject({ message: 'No pool created' }); return reject({ message: 'No pool created' });
resolve(this.torPool.instances.map((i) => ( { 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 } )) ); resolve(this.torPool.instances.map(instance_info) );
});
}).bind(this));
server.expose('queryInstanceByName', (function (instance_name) {
return new Promise((resolve, reject) => {
if (!this.torPool)
return reject({ message: 'No pool created' });
let i = this.torPool.instance_by_name(instance_name);
if (!i)
return reject({ message: `Instance "${instance_name}"" does not exist` });
resolve(instance_info(i));
});
}).bind(this));
server.expose('queryInstanceAt', (function (index) {
return new Promise((resolve, reject) => {
if (!this.torPool)
return reject({ message: 'No pool created' });
let i = this.torPool.instance_at(index);
if (!i)
return reject({ message: `Instance at "${i}"" does not exist` });
resolve(instance_info(this.torPool.instance_at(index)));
}); });
}).bind(this)); }).bind(this));

View file

@ -23,7 +23,7 @@ var logger = winston.createLogger({
}); });
const WAIT_FOR_CREATE = 120000; const WAIT_FOR_CREATE = 120000;
const PAGE_LOAD_TIME = 30000; const PAGE_LOAD_TIME = 60000;
describe('TorProcess', function () { describe('TorProcess', function () {
var tor = new (TorRouter.TorProcess)(nconf.get('torPath'), { DataDirectory: nconf.get('parentDataDirectory'), ProtocolWarnings: 0 }, null, logger); var tor = new (TorRouter.TorProcess)(nconf.get('torPath'), { DataDirectory: nconf.get('parentDataDirectory'), ProtocolWarnings: 0 }, null, logger);
@ -281,20 +281,6 @@ describe('TorPool', function () {
}); });
describe('#new_ips(index)', function () {
this.timeout(5000);
it('should signal to retrieve a new identity to all instances', function (done) {
torPool.new_ips(done);
});
});
describe('#new_ip_at(instance_name)', function () {
this.timeout(5000);
it('should signal to retrieve a new identity identified by index', function (done) {
torPool.new_ip_at(0, done);
});
});
describe('#set_config_all(keyword, value)', function () { describe('#set_config_all(keyword, value)', function () {
it('should set configuration on all active instances', function (done) { it('should set configuration on all active instances', function (done) {
this.timeout(5000); this.timeout(5000);
@ -457,7 +443,7 @@ describe('HTTPServer', function () {
req.on('response', function (res) { req.on('response', function (res) {
done(); done();
}) });
}); });
}); });
@ -476,7 +462,7 @@ describe('HTTPServer', function () {
req.on('response', function (res) { req.on('response', function (res) {
done(); done();
}) });
}); });
}); });
@ -652,6 +638,34 @@ describe('ControlServer - RPC', function () {
}); });
}); });
describe('#queryInstanceByName(instance_name)', function () {
this.timeout(3000);
it('should return a single instance', function (done) {
rpcClient.invoke('queryInstanceByName', ['instance-1'], function (error, raw) {
if (error)
return done(error);
var instance = JSON.parse(raw).result;
done(null, (typeof(instance.name) !== undefined) && (instance.name !== null));
});
});
});
describe('#queryInstanceAt(index)', function () {
this.timeout(3000);
it('should return a single instance', function (done) {
rpcClient.invoke('queryInstanceAt', [0], function (error, raw) {
if (error)
return done(error);
var instance = JSON.parse(raw).result;
done(null, (typeof(instance.name) !== undefined) && (instance.name !== null));
});
});
});
describe('#newIdentites()', function () { describe('#newIdentites()', function () {
this.timeout(3000); this.timeout(3000);
it('should request new identities for all instances', function (done) { it('should request new identities for all instances', function (done) {