2017-01-31 15:56:42 +00:00
|
|
|
/* From http://stackoverflow.com/questions/1985260/javascript-array-rotate */
|
|
|
|
Array.prototype.rotate = (function() {
|
|
|
|
// save references to array functions to make lookup faster
|
|
|
|
var push = Array.prototype.push,
|
|
|
|
splice = Array.prototype.splice;
|
|
|
|
|
|
|
|
return function(count) {
|
|
|
|
var len = this.length >>> 0, // convert to uint
|
|
|
|
count = count >> 0; // convert to int
|
|
|
|
|
|
|
|
// convert count to value in range [0, len)
|
|
|
|
count = ((count % len) + len) % len;
|
|
|
|
|
|
|
|
// use splice.call() instead of this.splice() to make function generic
|
|
|
|
push.apply(this, splice.call(this, 0, count));
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
})();
|
|
|
|
|
|
|
|
const EventEmitter = require('eventemitter2').EventEmitter2;
|
|
|
|
const async = require('async');
|
|
|
|
const TorProcess = require('./TorProcess');
|
|
|
|
const temp = require('temp');
|
|
|
|
const _ = require('lodash');
|
|
|
|
|
|
|
|
temp.track();
|
|
|
|
|
|
|
|
class TorPool extends EventEmitter {
|
2017-01-31 23:11:36 +00:00
|
|
|
constructor(tor_path, config, logger) {
|
2017-01-31 15:56:42 +00:00
|
|
|
super();
|
|
|
|
|
|
|
|
config = config || {};
|
|
|
|
|
|
|
|
this.tor_config = config;
|
|
|
|
this.tor_path = tor_path || 'tor';
|
|
|
|
this._instances = [];
|
2017-01-31 23:11:36 +00:00
|
|
|
this.logger = logger;
|
2017-01-31 15:56:42 +00:00
|
|
|
}
|
|
|
|
|
2017-03-26 01:02:56 +00:00
|
|
|
get instances() { return this._instances.filter((tor) => tor.ready).slice(0); }
|
2017-01-31 15:56:42 +00:00
|
|
|
|
|
|
|
create_instance(callback) {
|
|
|
|
let config = _.extend({}, this.tor_config)
|
2017-01-31 23:11:36 +00:00
|
|
|
let instance = new TorProcess(this.tor_path, config, this.logger);
|
2017-01-31 15:56:42 +00:00
|
|
|
instance.create((error) => {
|
|
|
|
if (error) return callback(error);
|
|
|
|
this._instances.push(instance);
|
2017-03-22 17:08:50 +00:00
|
|
|
|
2017-01-31 15:56:42 +00:00
|
|
|
instance.once('error', callback)
|
|
|
|
instance.once('ready', () => {
|
2017-03-26 01:02:56 +00:00
|
|
|
this.emit('instance_created', instance);
|
2017-01-31 23:11:36 +00:00
|
|
|
callback && callback(null, instance);
|
2017-01-31 15:56:42 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
create(instances, callback) {
|
|
|
|
if (!Number(instances)) return callback(null, []);
|
|
|
|
async.map(Array.from(Array(Number(instances))), (nothing, next) => {
|
|
|
|
this.create_instance(next);
|
2017-01-31 23:11:36 +00:00
|
|
|
}, (callback || (() => {})));
|
2017-01-31 15:56:42 +00:00
|
|
|
}
|
|
|
|
|
2017-03-25 00:11:06 +00:00
|
|
|
remove(instances, callback) {
|
|
|
|
let instances_to_remove = this._instances.splice(0, instances);
|
|
|
|
async.each(instances_to_remove, (instance, next) => {
|
|
|
|
instance.exit(next);
|
|
|
|
}, callback);
|
|
|
|
}
|
|
|
|
|
2017-01-31 15:56:42 +00:00
|
|
|
next() {
|
2017-01-31 23:11:36 +00:00
|
|
|
this._instances = this._instances.rotate(1);
|
2017-01-31 15:56:42 +00:00
|
|
|
return this.instances[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
exit() {
|
|
|
|
this.instances.forEach((tor) => tor.exit());
|
|
|
|
}
|
|
|
|
|
|
|
|
new_ips() {
|
|
|
|
this.instances.forEach((tor) => tor.new_ip());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = TorPool;
|