tor-router/lib/Tor.js
Zachary Boyd 45633936f3 final
2015-12-29 21:45:20 -05:00

126 lines
3.2 KiB
JavaScript

'use strict';
const ejs = require('ejs');
const shell = require('shelljs');
const _ = require('lodash');
const DockerPool = require('./DockerPool');
const child = require('child_process');
const uuid = require('uuid');
const es = require('event-stream');
const base32 = require('base32');
const winston = require('winston');
const temp = require('temp');
const async = require('async')
const fs = require('fs');
temp.track();
const Tor = (function () {
const TOR_IMAGE = 'znetstar/tor';
const NAME = Symbol('name');
const CONTAINER = Symbol('container');
const LOG_MESSAGES = Symbol('log messages');
const LOG_MESSAGE = '[Tor Client <%= id %>]: <%= message %>';
return class Tor {
constructor(options, pool, log, data_dir) {
if (!pool) {
pool = new DockerPool();
}
if (!(pool instanceof DockerPool)) {
throw new Error('Second argument is not a DockerPool');
}
this.pool = pool;
this.data_dir = data_dir || temp.mkdirSync();
this.docker = pool.host;
this[LOG_MESSAGES] = !!log;
this[NAME] = 'tor-'+(function () {
let buf = new Buffer(16);
uuid.v4(null, buf, 0);
return base32.encode(buf);
})();
}
get container() {
if (this[CONTAINER]) {
return this[CONTAINER];
} else {
return null;
}
}
srv(callback) {
var tor = this;
async.waterfall([
function ($next) {
let container = tor[CONTAINER];
container.inspect($next);
},
function (data, $next) {
let ip = data.NetworkSettings.IPAddress;
if (!ip || ip === '') {
return $next(new Error('no ip'));
}
$next(null, { host: (ip), port: 9050, dns_port: 9053 });
}
], callback)
}
create(callback) {
var tor = this;
async.waterfall([
function ($next) {
temp.open('txt',function (err, file) {
if (file) {
fs.write(file.fd, shell.cat(__dirname+'/../config/torrc'));
fs.close(file.fd)
}
$next(err, (file && file.path));
});
},
function (path, $next) {
tor.docker.run(TOR_IMAGE, [], null, { ExposedPorts: { '9050/tcp':{}, '9053/udp':{} } }, { Binds: [ path+':/etc/tor/torrc:ro' ] }, function (error, data, container) {
container.remove();
}).on('container', (function (container) {
var tor = this;
this[CONTAINER] = container;
let remove_cont = (function (code) {
container.stop(function () {
container.remove(function (err) {
process.exit();
});
});
})
process.on('SIGINT', remove_cont);
process.on('uncaughtException', remove_cont);
process.on('exit', remove_cont);
container.attach({ stream: true, stdout: true }, function (err,stream) {
stream.pipe(es.map(function (data, cb){
if (tor[LOG_MESSAGES])
process.stdout.write(ejs.render(LOG_MESSAGE, { id: container.id, message: (data.toString('utf8')) }))
cb();
}));
});
var srv = null;
async.until((function () { return srv; }), function ($next) {
tor.srv(function (err, $srv) {
srv = $srv;
setTimeout($next, 1000);
});
}, function (err) {
callback(null, srv);
});
}).bind(tor));
}
], callback);
}
};
})();
module.exports = Tor;