From def036b79f27aba66d6fc2517b181cc3bb3ab481 Mon Sep 17 00:00:00 2001 From: Gordon Hall Date: Sun, 20 Apr 2014 14:04:52 -0400 Subject: [PATCH] setup connection pool and auto handling of bad seeds --- examples/PeerDiscovery.js | 9 +------ lib/PeerManager.js | 52 ++++++++++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/examples/PeerDiscovery.js b/examples/PeerDiscovery.js index 2662698..dfbec65 100644 --- a/examples/PeerDiscovery.js +++ b/examples/PeerDiscovery.js @@ -1,11 +1,4 @@ var PeerManager = require('../lib/PeerManager'); var peerman = new PeerManager(); -peerman.discoverPeers(function(err, peers) { - // we can use this array of peers to add to the manager - // but let's limit it to 6 connections for this example - var p = 0; - do { peerman.addPeer(peers[p]); p++; } while (p < 6); - // then we can start the manager - peerman.start(); -}); +peerman.discover({ limit: 6 }).start(); diff --git a/lib/PeerManager.js b/lib/PeerManager.js index d18bd98..85cbb22 100644 --- a/lib/PeerManager.js +++ b/lib/PeerManager.js @@ -3,7 +3,6 @@ var extend = imports.extend || require('extend'); var log = imports.log || require('../util/log'); var bitcoreDefaults = imports.config || require('../config'); var Connection = imports.Connection || require ('./Connection'); - var Peer = imports.Peer || require('./Peer'); GetAdjustedTime = imports.GetAdjustedTime || function () { @@ -18,6 +17,7 @@ function PeerManager(config) { this.timer = null; this.peers = []; + this.pool = []; this.connections = []; this.isConnected = false; this.peerDiscovery = false; @@ -30,8 +30,7 @@ function PeerManager(config) { // keep track of tried seeds and results this.seeds = { resolved: [], - failed: [], - results: {} + failed: [] }; } @@ -68,6 +67,13 @@ PeerManager.prototype.addPeer = function(peer, port) { } }; +PeerManager.prototype.removePeer = function(peer) { + var index = this.peers.indexOf(peer); + var exists = !!~index; + if (exists) this.peers.splice(index, 1); + return exists; +}; + PeerManager.prototype.checkStatus = function checkStatus() { // Make sure we are connected to all forcePeers if(this.peers.length) { @@ -91,7 +97,7 @@ PeerManager.prototype.checkStatus = function checkStatus() { }; PeerManager.prototype.connectTo = function(peer) { - log.info('connecting to '+peer); + log.info('connecting to ' + peer); try { return this.addConnection(peer.createConnection(), peer); } catch (e) { @@ -181,10 +187,16 @@ PeerManager.prototype.handleError = function(e) { }; PeerManager.prototype.handleDisconnect = function(e) { - log.info('disconnected from peer '+e.peer); + log.info('disconnected from peer ' + e.peer); var i = this.connections.indexOf(e.conn); if(i != -1) this.connections.splice(i, 1); + this.removePeer(e.peer); + log.info('replacing peer with one from the pool of: ' + this.pool.length); + if (this.pool.length) { + this.addPeer(this.pool.pop()); + } + if(!this.connections.length) { this.emit('netDisconnected'); this.isConnected = false; @@ -219,13 +231,15 @@ PeerManager.prototype.getActiveConnections = function () { return this.connections.slice(0); }; -PeerManager.prototype.discoverPeers = function(callback) { +PeerManager.prototype.discover = function(options, callback) { var self = this; var async = imports.async || require('async'); var dns = imports.dns || require('dns'); var networks = imports.networks || require('../networks'); var seeds = networks[self.config.network].dnsSeeds; + self.limit = options.limit || 12; + var dnsExecutor = seeds.map(function(seed) { return function(done) { // have we already resolved this seed? @@ -240,17 +254,30 @@ PeerManager.prototype.discoverPeers = function(callback) { return done(null, []); } - // otherwise resolve the dns seed to get some peers log.info('resolving dns seed '+ seed); + dns.resolve(seed, function(err, peers) { if (err) { log.err('failed to resolve dns seed '+ seed, err); self.seeds.failed.push(seed); return done(null, []); } + log.info('found '+ peers.length + ' peers from ' + seed); self.seeds.resolved.push(seed); - self.seeds.results[seed] = peers; + + // transform that list into a list of Peer instances + peers = peers.map(function(ip) { + return new Peer(ip, networks.defaultClientPort); + }); + + peers.forEach(function(p) { + if (self.peers.length < self.limit) self.addPeer(p); + else self.pool.push(p); + }); + + self.emit('peers', peers); + return done(null, peers); }); @@ -266,13 +293,10 @@ PeerManager.prototype.discoverPeers = function(callback) { peers = peers.concat(peerlist); }); - // transform that list into a list of Peer instances - peers = peers.map(function(ip) { - return new Peer(ip, networks.defaultClientPort); - }); - - callback(null, peers); + if (typeof callback === 'function') callback(null, peers); }); + + return self; }; module.exports = require('soop')(PeerManager);