diff --git a/Connection.js b/Connection.js index 319a723e3..27a4fb618 100644 --- a/Connection.js +++ b/Connection.js @@ -22,11 +22,20 @@ var nonce = util.generateNonce(); var BIP0031_VERSION = 60000; -function Connection(socket, peer) { +function Connection(socket, peer, opts) { Connection.super(this, arguments); + + this.options = opts || {}; + this.socket = socket; this.peer = peer; + // check for socks5 proxy options and construct a proxied socket + if (this.options.proxy) { + var Socks5Client = imports.Socks5Client || require('socks5-client'); + this.socket = new Socks5Client(opts.proxy.host, opts.proxy.port); + } + // A connection is considered "active" once we have received verack this.active = false; // The version incoming packages are interpreted as @@ -36,7 +45,7 @@ function Connection(socket, peer) { // The (claimed) height of the remote peer's block chain this.bestHeight = 0; // Is this an inbound connection? - this.inbound = !!socket.server; + this.inbound = !!this.socket.server; // Have we sent a getaddr on this connection? this.getaddr = false; @@ -54,6 +63,12 @@ function Connection(socket, peer) { } Connection.parent = imports.parent || require('events').EventEmitter; +Connection.prototype.open = function(callback) { + if (typeof callback === 'function') this.once('connect', callback); + this.socket.connect(this.peer.port, this.peer.host); + return this; +}; + Connection.prototype.setupHandlers = function () { this.socket.addListener('connect', this.handleConnect.bind(this)); this.socket.addListener('error', this.handleError.bind(this)); diff --git a/PeerManager.js b/PeerManager.js index d8229867f..273d9f6d6 100644 --- a/PeerManager.js +++ b/PeerManager.js @@ -95,8 +95,8 @@ PeerManager.prototype.connectTo = function(peer) { } }; -PeerManager.prototype.addConnection = function(socketConn, peer) { - var conn = new Connection(socketConn, peer); +PeerManager.prototype.addConnection = function(socketConn, peer, opts) { + var conn = new Connection(socketConn, peer, opts); this.connections.push(conn); this.emit('connection', conn); diff --git a/examples/ConnectionTor.js b/examples/ConnectionTor.js new file mode 100644 index 000000000..aa006f677 --- /dev/null +++ b/examples/ConnectionTor.js @@ -0,0 +1,27 @@ +var Peer = require('../Peer'); +var Connection = require('../Connection'); +var dns = require('dns'); + +// get a peer from dns seed +dns.resolve('dnsseed.bluematt.me', function(err, seeds) { + // use the first peer + var peer = new Peer(seeds[0], 8333); + + // create a connection without an existing socket + // but specify a socks5 proxy to create a socket + // that's bound to that proxy in it's place + var connection = new Connection(null, peer, { + proxy: { host: '127.0.0.1', port: 9050 } + }); + + connection.open(); + + connection.on('connect', function(data) { + console.log('connected through socks5!'); + }); + + connection.on('error', function(err) { + console.log(err); + }); + +}); diff --git a/package.json b/package.json index 621003c53..3bd99003a 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,10 @@ { "name": "Ryan X. Charles", "email": "ryan@bitpay.com" + }, + { + "name": "Gordon Hall", + "email": "gordon@bitpay.com" } ], "keywords": [ @@ -63,6 +67,7 @@ "commander": "=2.1.0", "browserify-bignum": "git://github.com/maraoz/browserify-bignum.git", "browserify-buffertools": "git://github.com/maraoz/browserify-buffertools.git", + "socks5-client": "~0.3.6", "brfs": "=1.0.0", "chai": "=1.9.1", "uglifyify": "=1.2.3" diff --git a/test/test.Connection.js b/test/test.Connection.js index 868297384..cbf98ce46 100644 --- a/test/test.Connection.js +++ b/test/test.Connection.js @@ -23,6 +23,13 @@ describe('Connection', function() { var c = new Connection(mSocket, mPeer); should.exist(c); }); + it('should create a proxied socket if instructed', function() { + var mPeer; + var c = new Connection(null, mPeer, { + proxy: { host: 'localhost', port: 9050 } + }); + should.exist(c.socket); + }); });