dispatch-proxy
Advanced tools
Comparing version 0.0.10 to 0.1.0
@@ -1,5 +0,11 @@ | ||
var Dispatcher, | ||
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; | ||
var Dispatcher, EventEmitter, | ||
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, | ||
__hasProp = {}.hasOwnProperty, | ||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; | ||
module.exports = Dispatcher = (function() { | ||
EventEmitter = require('events').EventEmitter; | ||
module.exports = Dispatcher = (function(_super) { | ||
__extends(Dispatcher, _super); | ||
function Dispatcher(addresses) { | ||
@@ -12,3 +18,3 @@ this.addresses = addresses; | ||
Dispatcher.prototype.prioritiesSum = function() { | ||
Dispatcher.prototype._prioritiesSum = function() { | ||
var priority; | ||
@@ -39,3 +45,3 @@ return ((function() { | ||
currentRatio = (this.connectionsByAddress[address.address] / this.connectionsTotal) || 0; | ||
priorityRatio = address.priority / this.prioritiesSum(); | ||
priorityRatio = address.priority / this._prioritiesSum(); | ||
ratioDiff = priorityRatio - currentRatio; | ||
@@ -52,6 +58,6 @@ if (ratioDiff > maxRatioDiff) { | ||
if (maxRatioDiff < 0.000001) { | ||
this._dispatch(prevailingAddress); | ||
this._increment(prevailingAddress); | ||
return prevailingAddress; | ||
} else { | ||
this._dispatch(availableAddress); | ||
this._increment(availableAddress); | ||
return availableAddress; | ||
@@ -61,3 +67,3 @@ } | ||
Dispatcher.prototype._dispatch = function(address) { | ||
Dispatcher.prototype._increment = function(address) { | ||
var _base; | ||
@@ -78,2 +84,2 @@ (_base = this.connectionsByAddress)[address] || (_base[address] = 0); | ||
})(); | ||
})(EventEmitter); |
@@ -1,2 +0,2 @@ | ||
var Dispatcher, HttpProxy, Logger, SocksProxy, crypto, emit, format, inspect, log, logger, os, program, _ref, | ||
var HttpProxy, Logger, SocksProxy, crypto, inspect, logger, os, program, | ||
__slice = [].slice; | ||
@@ -12,6 +12,4 @@ | ||
Logger = require('./logger'); | ||
Logger = require('tmpl-log'); | ||
Dispatcher = require('./dispatcher'); | ||
SocksProxy = require('./proxy/socks'); | ||
@@ -21,6 +19,6 @@ | ||
logger = (_ref = new Logger({ | ||
logger = new Logger({ | ||
tab: 10, | ||
gutter: ' ' | ||
}).registerStyle('b', ['bold']).registerStyle('s', ['green']).registerStyle('i', ['cyan']).registerStyle('e', ['red']).registerStyle('a', ['b', 'underline']).registerEvent('request', '<b-i>request').registerEvent('dispatch', '<b-i>dispatch').registerEvent('connect', '<b-s>connect').registerEvent('response', '<b-s>response').registerEvent('error', '<b-e>error').registerEvent('end', '<b-i>end').registerMode('default', ['error']).registerMode('debug', true), log = _ref.log, emit = _ref.emit, format = _ref.format, _ref); | ||
}).registerTag('b', ['bold']).registerTag('s', ['green']).registerTag('i', ['cyan']).registerTag('e', ['red']).registerTag('a', ['b', 'underline']).registerEvent('request', '<b><i>request').registerEvent('dispatch', '<b><i>dispatch').registerEvent('connect', '<b><s>connect').registerEvent('response', '<b><s>response').registerEvent('error', '<b><e>error').registerEvent('end', '<b><i>end').registerMode('default', ['error']).registerMode('debug', true); | ||
@@ -30,3 +28,3 @@ program.version('0.0.10'); | ||
program.command('list').description('list all available network interfaces').action(function() { | ||
var address, addrs, family, interfaces, internal, name, opts, _i, _len, _ref1, _results; | ||
var address, addrs, family, interfaces, internal, name, opts, _i, _len, _ref, _results; | ||
interfaces = os.networkInterfaces(); | ||
@@ -36,5 +34,5 @@ _results = []; | ||
addrs = interfaces[name]; | ||
log("<b>" + name); | ||
logger.log("<b>" + name); | ||
for (_i = 0, _len = addrs.length; _i < _len; _i++) { | ||
_ref1 = addrs[_i], address = _ref1.address, family = _ref1.family, internal = _ref1.internal; | ||
_ref = addrs[_i], address = _ref.address, family = _ref.family, internal = _ref.internal; | ||
opts = []; | ||
@@ -47,5 +45,5 @@ if (family) { | ||
} | ||
log((" <a>" + address + "</>") + (opts.length > 0 ? " (" + (opts.join(', ')) + ")" : '')); | ||
logger.log((" <a>" + address + "</>") + (opts.length > 0 ? " (" + (opts.join(', ')) + ")" : '')); | ||
} | ||
_results.push(log('')); | ||
_results.push(logger.log('')); | ||
} | ||
@@ -56,3 +54,3 @@ return _results; | ||
program.command('start').usage('[options] [addresses]').description('start a proxy server').option('-H, --host <h>', 'which host to accept connections from (defaults to localhost)', String).option('-p, --port <p>', 'which port to listen to for connections (defaults to 8080 for HTTP proxy, 1080 for SOCKS proxy)', Number).option('--http', 'start an http proxy server', Boolean).option('--debug', 'log debug info in the console', Boolean).action(function() { | ||
var addr, address, addresses, addrs, arg, args, debug, dispatcher, host, http, https, name, port, priority, proxy, type, _arg, _i, _j, _k, _len, _len1, _ref1, _ref2; | ||
var addr, address, addresses, addrs, arg, args, debug, host, http, https, name, port, priority, proxy, type, _arg, _i, _j, _k, _len, _len1, _ref, _ref1; | ||
args = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), _arg = arguments[_i++]; | ||
@@ -65,5 +63,5 @@ port = _arg.port, host = _arg.host, http = _arg.http, https = _arg.https, debug = _arg.debug; | ||
if (args.length === 0) { | ||
_ref1 = os.networkInterfaces(); | ||
for (name in _ref1) { | ||
addrs = _ref1[name]; | ||
_ref = os.networkInterfaces(); | ||
for (name in _ref) { | ||
addrs = _ref[name]; | ||
for (_j = 0, _len = addrs.length; _j < _len; _j++) { | ||
@@ -82,3 +80,3 @@ addr = addrs[_j]; | ||
arg = args[_k]; | ||
_ref2 = arg.split('@'), address = _ref2[0], priority = _ref2[1]; | ||
_ref1 = arg.split('@'), address = _ref1[0], priority = _ref1[1]; | ||
priority = priority ? parseInt(priority) : 1; | ||
@@ -92,7 +90,6 @@ addresses.push({ | ||
host || (host = 'localhost'); | ||
dispatcher = new Dispatcher(addresses); | ||
if (http) { | ||
port || (port = 8080); | ||
type = 'HTTP'; | ||
proxy = new HttpProxy(dispatcher, port, host); | ||
proxy = new HttpProxy(addresses, port, host); | ||
proxy.on('request', function(_arg1) { | ||
@@ -102,23 +99,23 @@ var clientRequest, id, localAddress, serverRequest; | ||
id = (crypto.randomBytes(3)).toString('hex'); | ||
emit('request', "[" + id + "] <a>" + clientRequest.url + "</>"); | ||
emit('dispatch', "[" + id + "] <a>" + localAddress + "</>"); | ||
logger.emit('request', "[" + id + "] <a>" + clientRequest.url + "</>"); | ||
logger.emit('dispatch', "[" + id + "] <a>" + localAddress + "</>"); | ||
serverRequest.on('response', function(serverResponse) { | ||
return emit('response', "[" + id + "] <magenta-b>" + serverResponse.statusCode + "</>"); | ||
return logger.emit('response', "[" + id + "] <magenta-b>" + serverResponse.statusCode + "</>"); | ||
}).on('error', function(err) { | ||
return emit('error', "[" + id + "] clientRequest\n" + (escape(err.stack))); | ||
return logger.emit('error', "[" + id + "] clientRequest\n" + (escape(err.stack))); | ||
}).on('end', function() { | ||
return emit('end', "[" + id + "] serverRequest"); | ||
return logger.emit('end', "[" + id + "] serverRequest"); | ||
}); | ||
return clientRequest.on('error', function(err) { | ||
return emit('error', "[" + id + "] clientRequest\n" + (escape(err.stack))); | ||
return logger.emit('error', "[" + id + "] clientRequest\n" + (escape(err.stack))); | ||
}).on('end', function() { | ||
return emit('end', "[" + id + "] clientRequest"); | ||
return logger.emit('end', "[" + id + "] clientRequest"); | ||
}); | ||
}).on('error', function(err) { | ||
return emit('error', "server\n" + (escape(err.stack))); | ||
return logger.emit('error', "server\n" + (escape(err.stack))); | ||
}); | ||
} else { | ||
port || (port = 1080); | ||
type = 'SOCKS5'; | ||
proxy = new SocksProxy(dispatcher, port, host); | ||
type = 'SOCKS'; | ||
proxy = new SocksProxy(addresses, port, host); | ||
proxy.on('request', function(_arg1) { | ||
@@ -128,27 +125,27 @@ var clientConnection, host, id, localAddress, port, serverConnection; | ||
id = (crypto.randomBytes(3)).toString('hex'); | ||
emit('request', "[" + id + "] <a>" + host + "</><b>:" + port + "</>"); | ||
emit('dispatch', "[" + id + "] <a>" + localAddress + "</>"); | ||
logger.emit('request', "[" + id + "] <a>" + host + "</><b>:" + port + "</>"); | ||
logger.emit('dispatch', "[" + id + "] <a>" + localAddress + "</>"); | ||
serverConnection.on('connect', function() { | ||
return emit('connect', "[" + id + "] <a>" + host + "</><b>:" + port + "</>"); | ||
return logger.emit('connect', "[" + id + "] <a>" + host + "</><b>:" + port + "</>"); | ||
}).on('error', function(err) { | ||
return emit('error', "[" + id + "] serverConnection\n" + (escape(err.stack))); | ||
return logger.emit('error', "[" + id + "] serverConnection\n" + (escape(err.stack))); | ||
}).on('end', function() { | ||
return emit('end', "[" + id + "] serverConnection"); | ||
return logger.emit('end', "[" + id + "] serverConnection"); | ||
}); | ||
return clientConnection.on('error', function(err) { | ||
return emit('error', "[" + id + "] clientConnection\n" + (escape(err.stack))); | ||
return logger.emit('error', "[" + id + "] clientConnection\n" + (escape(err.stack))); | ||
}).on('end', function() { | ||
return emit('end', "[" + id + "] clientConnection"); | ||
return logger.emit('end', "[" + id + "] clientConnection"); | ||
}); | ||
}).on('error', function(err) { | ||
return emit('error', "server\n" + (escape(err.stack))); | ||
}).on('clientError', function(err, data) { | ||
return emit('error', "client\n" + (escape(err.message)) + "\n<b>Received:</>\n" + (escape(inspect(data))) + "\n" + (escape(data.toString()))); | ||
return logger.emit('error', "server\n" + (escape(err.stack))); | ||
}).on('socksError', function(err) { | ||
return logger.emit('error', "socks\n" + (escape(err.message))); | ||
}); | ||
} | ||
return log("<bold-magenta>" + type + "</> server started on <a>" + host + "</><b>:" + port + "</>\nDispatching to addresses " + (((function() { | ||
var _l, _len2, _ref3, _results; | ||
return logger.log("<b><magenta>" + type + "</></> server started on <a>" + host + "</><b>:" + port + "</>\nDispatching to addresses " + (((function() { | ||
var _l, _len2, _ref2, _results; | ||
_results = []; | ||
for (_l = 0, _len2 = addresses.length; _l < _len2; _l++) { | ||
_ref3 = addresses[_l], address = _ref3.address, priority = _ref3.priority; | ||
_ref2 = addresses[_l], address = _ref2.address, priority = _ref2.priority; | ||
_results.push("<a>" + address + "</><b>@" + priority + "</>"); | ||
@@ -155,0 +152,0 @@ } |
@@ -1,2 +0,2 @@ | ||
var EventEmitter, HttpProxy, http, url, | ||
var Dispatcher, HttpProxy, http, url, | ||
__hasProp = {}.hasOwnProperty, | ||
@@ -9,3 +9,3 @@ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; | ||
EventEmitter = require('events').EventEmitter; | ||
Dispatcher = require('../dispatcher'); | ||
@@ -15,6 +15,6 @@ module.exports = HttpProxy = (function(_super) { | ||
function HttpProxy(dispatcher, listenPort, listenHost) { | ||
function HttpProxy(addresses, listenPort, listenHost) { | ||
var agent, | ||
_this = this; | ||
HttpProxy.__super__.constructor.apply(this, arguments); | ||
HttpProxy.__super__.constructor.call(this, addresses); | ||
agent = new http.Agent({ | ||
@@ -25,3 +25,3 @@ maxSockets: Infinity | ||
var localAddress, options, serverRequest; | ||
localAddress = dispatcher.dispatch(); | ||
localAddress = _this.dispatch(); | ||
options = url.parse(clientRequest.url); | ||
@@ -40,6 +40,5 @@ options.localAddress = localAddress; | ||
return clientResponse.end(); | ||
}).on('end', function() { | ||
return _this.free(localAddress); | ||
}); | ||
serverRequest.on('end', function() { | ||
return dispatcher.free(localAddress); | ||
}); | ||
return _this.emit('request', { | ||
@@ -56,2 +55,2 @@ clientRequest: clientRequest, | ||
})(EventEmitter); | ||
})(Dispatcher); |
@@ -1,2 +0,2 @@ | ||
var EventEmitter, STATUS, SocksProxy, net, socks, | ||
var Dispatcher, SocksProxy, net, socks, | ||
__hasProp = {}.hasOwnProperty, | ||
@@ -7,52 +7,76 @@ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; | ||
EventEmitter = require('events').EventEmitter; | ||
socks = require('socks-handler'); | ||
socks = require('../socks'); | ||
Dispatcher = require('../dispatcher'); | ||
STATUS = require('../socks/const').STATUS; | ||
module.exports = SocksProxy = (function(_super) { | ||
__extends(SocksProxy, _super); | ||
function SocksProxy(dispatcher, listenPort, listenHost) { | ||
function SocksProxy(addresses, listenPort, listenHost) { | ||
var _this = this; | ||
SocksProxy.__super__.constructor.apply(this, arguments); | ||
this.server = socks.createServer(function(clientConnection, host, port, handshake) { | ||
var localAddress, serverConnection, _responded; | ||
localAddress = dispatcher.dispatch(); | ||
serverConnection = net.createConnection({ | ||
host: host, | ||
port: port, | ||
localAddress: localAddress | ||
}); | ||
_responded = false; | ||
serverConnection.on('connect', function() { | ||
_responded = true; | ||
return handshake(STATUS.SUCCESS); | ||
}).on('error', function(err) { | ||
if (!_responded) { | ||
_responded = true; | ||
switch (err.code) { | ||
case 'EHOSTUNREACH': | ||
return handshake(STATUS.HOST_UNREACHABLE); | ||
case 'ECONNREFUSED': | ||
return handshake(STATUS.CONNECTION_REFUSED); | ||
case 'ENETUNREACH': | ||
return handshake(STATUS.NETWORK_UNREACHABLE); | ||
default: | ||
return handshake(STATUS.SERVER_FAILURE); | ||
SocksProxy.__super__.constructor.call(this, addresses); | ||
this.server = net.createServer(function(clientConnection) { | ||
return socks.handle(clientConnection, function(err, handler) { | ||
if (err) { | ||
_this.emit('socksError', err); | ||
return; | ||
} | ||
handler.on('error', function(err) { | ||
return this.emit('socksError', err); | ||
}); | ||
return handler.on('request', function(_arg, callback) { | ||
var command, host, localAddress, onConnectError, port, serverConnection, version; | ||
version = _arg.version, command = _arg.command, host = _arg.host, port = _arg.port; | ||
if (command !== socks[5].COMMAND.CONNECT) { | ||
_this.emit('socksError', new Error("Unsupported command: " + command)); | ||
if (version === 5) { | ||
callback(socks[5].REQUEST_STATUS.COMMAND_NOT_SUPPORTED); | ||
} else { | ||
callback(socks[4].REQUEST_STATUS.REFUSED); | ||
} | ||
return; | ||
} | ||
} | ||
}).on('end', function() { | ||
return dispatcher.free(localAddress); | ||
localAddress = _this.dispatch(); | ||
serverConnection = net.createConnection({ | ||
port: port, | ||
host: host, | ||
localAddress: localAddress | ||
}); | ||
clientConnection.pipe(serverConnection).pipe(clientConnection); | ||
serverConnection.on('error', onConnectError = function(err) { | ||
var status; | ||
if (version === 5) { | ||
status = (function() { | ||
switch (err.code) { | ||
case 'EHOSTUNREACH': | ||
return socks[5].REQUEST_STATUS.HOST_UNREACHABLE; | ||
case 'ECONNREFUSED': | ||
return socks[5].REQUEST_STATUS.CONNECTION_REFUSED; | ||
case 'ENETUNREACH': | ||
return socks[5].REQUEST_STATUS.NETWORK_UNREACHABLE; | ||
default: | ||
return socks[5].REQUEST_STATUS.SERVER_FAILURE; | ||
} | ||
})(); | ||
} else { | ||
status = socks[4].REQUEST_STATUS.FAILED; | ||
} | ||
return callback(status); | ||
}).on('connect', function() { | ||
var status; | ||
serverConnection.removeListener('error', onConnectError); | ||
status = version === 5 ? socks[5].REQUEST_STATUS.SUCCESS : socks[4].REQUEST_STATUS.GRANTED; | ||
return callback(status); | ||
}).on('end', function() { | ||
return _this.free(localAddress); | ||
}); | ||
return _this.emit('request', { | ||
clientConnection: clientConnection, | ||
serverConnection: serverConnection, | ||
host: host, | ||
port: port, | ||
localAddress: localAddress | ||
}); | ||
}); | ||
}); | ||
clientConnection.pipe(serverConnection); | ||
serverConnection.pipe(clientConnection); | ||
return _this.emit('request', { | ||
serverConnection: serverConnection, | ||
clientConnection: clientConnection, | ||
host: host, | ||
port: port, | ||
localAddress: localAddress | ||
}); | ||
}); | ||
@@ -62,5 +86,2 @@ this.server.on('error', function(err) { | ||
}); | ||
this.server.on('clientError', function(err, data) { | ||
return _this.emit('clientError', err, data); | ||
}); | ||
this.server.listen(listenPort, listenHost); | ||
@@ -71,2 +92,2 @@ } | ||
})(EventEmitter); | ||
})(Dispatcher); |
@@ -5,3 +5,4 @@ { | ||
"author": "Alexandre Kirszenberg <a.kirszenberg@gmail.com>", | ||
"version": "0.0.10", | ||
"version": "0.1.0", | ||
"license": "MIT", | ||
"keywords": [ | ||
@@ -37,3 +38,5 @@ "dispatch", | ||
"dependencies": { | ||
"commander": "2.0.0" | ||
"commander": "2.0.0", | ||
"socks-handler": "0.2.0", | ||
"tmpl-log": "0.0.3" | ||
}, | ||
@@ -40,0 +43,0 @@ |
dispatch-proxy | ||
============== | ||
A SOCKS5/HTTP proxy that balances traffic between multiple internet connections. | ||
*Works on <b>Mac OS X</b>, <b>Windows</b> and <b>Linux</b>.* | ||
**Detailed installation instructions:** | ||
* Windows: [imgur album](http://imgur.com/a/0snis) | ||
* Max OS X: [imgur album](http://imgur.com/a/TSD5F) | ||
Installation | ||
------------ | ||
You'll need to have Node.JS >= 0.10.0 installed on your system. | ||
``` | ||
$ npm install -g dispatch-proxy | ||
``` | ||
To update: | ||
``` | ||
$ npm update -g dispatch-proxy | ||
``` | ||
Rationale | ||
@@ -8,4 +27,6 @@ --------- | ||
For example, my residence provides me with a cabled and wireless internet access. Both are capped at 1,200kB/s download/upload speed, but they can simultaneously run at full speed. My mobile internet access also provides me with 400kB/s download/upload speed. Combine all these with `dispatch` and a threaded download manager and you get a 2,800kB/s download and upload speed limit, which is considerably better :) | ||
For example, my residence provides me with a cabled and wireless internet access. Both are capped at 1,200kB/s download/upload speed, but they can simultaneously run at full speed. My mobile internet access also provides me with 400kB/s download/upload speed. | ||
Combine all of these with `dispatch` and a threaded download manager and you get a 2,800kB/s download and upload speed limit, which is considerably better :) | ||
Use-cases | ||
@@ -15,12 +36,8 @@ --------- | ||
* download a file through threaded downloading, effectively combining multiple connections' speed in one single file download, | ||
* create two proxies, assign to each its own interface, and run two apps simultaneously that use a different interface, | ||
* combine as many Wi-Fi networks/Ethernet/3G/4G connections as you have access to in one big, load balanced connection, | ||
* use it in conjunction with a threaded download manager, effectively combining multiple connections' speed in single file downloads, | ||
* create two proxies, assign to each its own interface, and run two apps simultaneously that use a different interface (e.g. for balancing download/upload), | ||
* create a hotspot proxy at home that connects through Ethernet and your 4G card for all your mobile devices, | ||
* etc. | ||
Installation | ||
------------ | ||
You'll need to have Node.JS installed on your system. | ||
Then, as a power user run `$ npm install -g dispatch-proxy`. | ||
Quick start | ||
@@ -33,2 +50,3 @@ ----------- | ||
Start a SOCKS proxy server on `localhost:1080`. Simply add this address as a SOCKS proxy in your system settings and your traffic will be automatically balanced between all available internet connections. | ||
Usage | ||
@@ -64,2 +82,3 @@ ----- | ||
``` | ||
Examples | ||
@@ -66,0 +85,0 @@ -------- |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
0
94
1
20556
3
10
336
+ Addedsocks-handler@0.2.0
+ Addedtmpl-log@0.0.3
+ Addedip@0.1.0(transitive)
+ Addedsocks-handler@0.2.0(transitive)
+ Addedthrough@2.3.4(transitive)
+ Addedtmpl-log@0.0.3(transitive)