Browse Source

setup connection pool and auto handling of bad seeds

patch-2
Gordon Hall 11 years ago
parent
commit
def036b79f
  1. 9
      examples/PeerDiscovery.js
  2. 52
      lib/PeerManager.js

9
examples/PeerDiscovery.js

@ -1,11 +1,4 @@
var PeerManager = require('../lib/PeerManager'); var PeerManager = require('../lib/PeerManager');
var peerman = new PeerManager(); var peerman = new PeerManager();
peerman.discoverPeers(function(err, peers) { peerman.discover({ limit: 6 }).start();
// 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();
});

52
lib/PeerManager.js

@ -3,7 +3,6 @@ var extend = imports.extend || require('extend');
var log = imports.log || require('../util/log'); var log = imports.log || require('../util/log');
var bitcoreDefaults = imports.config || require('../config'); var bitcoreDefaults = imports.config || require('../config');
var Connection = imports.Connection || require ('./Connection'); var Connection = imports.Connection || require ('./Connection');
var Peer = imports.Peer || require('./Peer'); var Peer = imports.Peer || require('./Peer');
GetAdjustedTime = imports.GetAdjustedTime || function () { GetAdjustedTime = imports.GetAdjustedTime || function () {
@ -18,6 +17,7 @@ function PeerManager(config) {
this.timer = null; this.timer = null;
this.peers = []; this.peers = [];
this.pool = [];
this.connections = []; this.connections = [];
this.isConnected = false; this.isConnected = false;
this.peerDiscovery = false; this.peerDiscovery = false;
@ -30,8 +30,7 @@ function PeerManager(config) {
// keep track of tried seeds and results // keep track of tried seeds and results
this.seeds = { this.seeds = {
resolved: [], resolved: [],
failed: [], failed: []
results: {}
}; };
} }
@ -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() { PeerManager.prototype.checkStatus = function checkStatus() {
// Make sure we are connected to all forcePeers // Make sure we are connected to all forcePeers
if(this.peers.length) { if(this.peers.length) {
@ -91,7 +97,7 @@ PeerManager.prototype.checkStatus = function checkStatus() {
}; };
PeerManager.prototype.connectTo = function(peer) { PeerManager.prototype.connectTo = function(peer) {
log.info('connecting to '+peer); log.info('connecting to ' + peer);
try { try {
return this.addConnection(peer.createConnection(), peer); return this.addConnection(peer.createConnection(), peer);
} catch (e) { } catch (e) {
@ -181,10 +187,16 @@ PeerManager.prototype.handleError = function(e) {
}; };
PeerManager.prototype.handleDisconnect = 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); var i = this.connections.indexOf(e.conn);
if(i != -1) this.connections.splice(i, 1); 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) { if(!this.connections.length) {
this.emit('netDisconnected'); this.emit('netDisconnected');
this.isConnected = false; this.isConnected = false;
@ -219,13 +231,15 @@ PeerManager.prototype.getActiveConnections = function () {
return this.connections.slice(0); return this.connections.slice(0);
}; };
PeerManager.prototype.discoverPeers = function(callback) { PeerManager.prototype.discover = function(options, callback) {
var self = this; var self = this;
var async = imports.async || require('async'); var async = imports.async || require('async');
var dns = imports.dns || require('dns'); var dns = imports.dns || require('dns');
var networks = imports.networks || require('../networks'); var networks = imports.networks || require('../networks');
var seeds = networks[self.config.network].dnsSeeds; var seeds = networks[self.config.network].dnsSeeds;
self.limit = options.limit || 12;
var dnsExecutor = seeds.map(function(seed) { var dnsExecutor = seeds.map(function(seed) {
return function(done) { return function(done) {
// have we already resolved this seed? // have we already resolved this seed?
@ -240,17 +254,30 @@ PeerManager.prototype.discoverPeers = function(callback) {
return done(null, []); return done(null, []);
} }
// otherwise resolve the dns seed to get some peers
log.info('resolving dns seed '+ seed); log.info('resolving dns seed '+ seed);
dns.resolve(seed, function(err, peers) { dns.resolve(seed, function(err, peers) {
if (err) { if (err) {
log.err('failed to resolve dns seed '+ seed, err); log.err('failed to resolve dns seed '+ seed, err);
self.seeds.failed.push(seed); self.seeds.failed.push(seed);
return done(null, []); return done(null, []);
} }
log.info('found '+ peers.length + ' peers from ' + seed); log.info('found '+ peers.length + ' peers from ' + seed);
self.seeds.resolved.push(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); return done(null, peers);
}); });
@ -266,13 +293,10 @@ PeerManager.prototype.discoverPeers = function(callback) {
peers = peers.concat(peerlist); peers = peers.concat(peerlist);
}); });
// transform that list into a list of Peer instances if (typeof callback === 'function') callback(null, peers);
peers = peers.map(function(ip) {
return new Peer(ip, networks.defaultClientPort);
});
callback(null, peers);
}); });
return self;
}; };
module.exports = require('soop')(PeerManager); module.exports = require('soop')(PeerManager);

Loading…
Cancel
Save