net: refactor host and peer list.
This commit is contained in:
parent
127a52aaf1
commit
25101f1784
@ -31,6 +31,7 @@ var Outpoint = require('../primitives/outpoint');
|
||||
var Output = require('../primitives/output');
|
||||
var TX = require('../primitives/tx');
|
||||
var Logger = require('../node/logger');
|
||||
var IP = require('../utils/ip');
|
||||
|
||||
/**
|
||||
* RPC
|
||||
@ -388,7 +389,7 @@ RPC.prototype.getnetworkinfo = co(function* getnetworkinfo(args) {
|
||||
});
|
||||
|
||||
RPC.prototype.addnode = co(function* addnode(args) {
|
||||
var i, node, cmd, seed, addr, peer;
|
||||
var node, cmd, addr, peer;
|
||||
|
||||
if (args.help || args.length !== 2)
|
||||
throw new RPCError('addnode "node" "add|remove|onetry"');
|
||||
@ -399,21 +400,15 @@ RPC.prototype.addnode = co(function* addnode(args) {
|
||||
|
||||
switch (cmd) {
|
||||
case 'add':
|
||||
this.pool.seeds.push(addr);
|
||||
this.pool.hosts.add(addr);
|
||||
break;
|
||||
case 'remove':
|
||||
for (i = 0; i < this.pool.seeds.length; i++) {
|
||||
seed = this.pool.seeds[i];
|
||||
if (seed.hostname === addr.hostname) {
|
||||
this.pool.seeds.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.pool.hosts.remove(addr.hostname);
|
||||
break;
|
||||
case 'onetry':
|
||||
if (!this.pool.peers.get(addr)) {
|
||||
peer = this.pool.createPeer(addr);
|
||||
this.pool.peers.addOutbound(peer);
|
||||
if (!this.pool.peers.get(addr.hostname)) {
|
||||
peer = this.pool.createPeer(addr.port, addr.host);
|
||||
this.pool.peers.add(peer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -422,15 +417,16 @@ RPC.prototype.addnode = co(function* addnode(args) {
|
||||
});
|
||||
|
||||
RPC.prototype.disconnectnode = co(function* disconnectnode(args) {
|
||||
var node, addr, peer;
|
||||
var addr, peer;
|
||||
|
||||
if (args.help || args.length !== 1)
|
||||
throw new RPCError('disconnectnode "node"');
|
||||
|
||||
node = toString(args[0]);
|
||||
addr = NetAddress.fromHostname(node, this.network);
|
||||
addr = toString(args[0]);
|
||||
addr = IP.parseHost(addr, this.network.port);
|
||||
|
||||
peer = this.pool.peers.get(addr.hostname);
|
||||
|
||||
peer = this.pool.peers.get(addr);
|
||||
if (peer)
|
||||
peer.destroy();
|
||||
|
||||
@ -439,15 +435,15 @@ RPC.prototype.disconnectnode = co(function* disconnectnode(args) {
|
||||
|
||||
RPC.prototype.getaddednodeinfo = co(function* getaddednodeinfo(args) {
|
||||
var out = [];
|
||||
var host, addr, peer;
|
||||
var addr, peer;
|
||||
|
||||
if (args.help || args.length < 1 || args.length > 2)
|
||||
throw new RPCError('getaddednodeinfo dummy ( "node" )');
|
||||
|
||||
if (args.length === 2) {
|
||||
host = toString(args[1]);
|
||||
addr = NetAddress.fromHostname(host, this.network);
|
||||
peer = this.pool.peers.get(addr);
|
||||
addr = toString(args[1]);
|
||||
addr = IP.parseHost(addr, this.network.port);
|
||||
peer = this.pool.peers.get(addr.hostname);
|
||||
if (!peer)
|
||||
throw new RPCError('Node has not been added.');
|
||||
return [this._toAddedNode(peer)];
|
||||
@ -548,7 +544,7 @@ RPC.prototype.ping = co(function* ping(args) {
|
||||
});
|
||||
|
||||
RPC.prototype.setban = co(function* setban(args) {
|
||||
var host, ip;
|
||||
var addr, peer;
|
||||
|
||||
if (args.help
|
||||
|| args.length < 2
|
||||
@ -557,15 +553,21 @@ RPC.prototype.setban = co(function* setban(args) {
|
||||
+ ' "add|remove" (bantime) (absolute)');
|
||||
}
|
||||
|
||||
host = toString(args[0]);
|
||||
ip = NetAddress.fromHostname(host, this.network);
|
||||
addr = toString(args[0]);
|
||||
addr = IP.parseHost(addr, this.network);
|
||||
|
||||
switch (args[1]) {
|
||||
case 'add':
|
||||
this.pool.ban(ip);
|
||||
peer = this.pool.peers.get(addr.hostname);
|
||||
if (peer) {
|
||||
this.pool.ban(peer);
|
||||
break;
|
||||
}
|
||||
this.pool.hosts.ban(addr.host);
|
||||
this.pool.hosts.remove(addr.hostname);
|
||||
break;
|
||||
case 'remove':
|
||||
this.pool.unban(ip);
|
||||
this.pool.hosts.unban(addr.host);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -579,11 +581,11 @@ RPC.prototype.listbanned = co(function* listbanned(args) {
|
||||
throw new RPCError('listbanned');
|
||||
|
||||
banned = [];
|
||||
keys = Object.keys(this.pool.hosts.misbehaving);
|
||||
keys = Object.keys(this.pool.hosts.banned);
|
||||
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
host = keys[i];
|
||||
time = this.pool.hosts.misbehaving[host];
|
||||
time = this.pool.hosts.banned[host];
|
||||
banned.push({
|
||||
address: host,
|
||||
banned_until: time + constants.BAN_TIME,
|
||||
|
||||
@ -2638,22 +2638,21 @@ Peer.prototype.sendCompact = function sendCompact() {
|
||||
this.send(new packets.SendCmpctPacket(0, version));
|
||||
};
|
||||
|
||||
/**
|
||||
* Check whether the peer is banned (banScore >= 100).
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Peer.prototype.isBanned = function isBanned() {
|
||||
return this.pool.hosts.isBanned(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Increase banscore on peer.
|
||||
* @param {Number} score
|
||||
*/
|
||||
|
||||
Peer.prototype.increaseBan = function increaseBan(score) {
|
||||
return this.pool.increaseBan(this, score);
|
||||
this.banScore += score;
|
||||
|
||||
if (this.banScore >= constants.BAN_SCORE) {
|
||||
this.logger.debug('Ban threshold exceeded (%s).', this.hostname);
|
||||
this.pool.ban(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
156
lib/net/pool.js
156
lib/net/pool.js
@ -471,7 +471,7 @@ Pool.prototype.unlisten = function unlisten() {
|
||||
*/
|
||||
|
||||
Pool.prototype.handleInbound = function handleInbound(socket) {
|
||||
var addr;
|
||||
var host;
|
||||
|
||||
if (!socket.remoteAddress) {
|
||||
this.logger.debug('Ignoring disconnected leech.');
|
||||
@ -479,27 +479,23 @@ Pool.prototype.handleInbound = function handleInbound(socket) {
|
||||
return;
|
||||
}
|
||||
|
||||
addr = NetAddress.fromSocket(socket, this.network);
|
||||
host = IP.normalize(socket.remoteAddress);
|
||||
|
||||
if (this.peers.inbound >= this.maxInbound) {
|
||||
this.logger.debug('Ignoring leech: too many inbound (%s).', addr.hostname);
|
||||
this.logger.debug('Ignoring leech: too many inbound (%s).', host);
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.hosts.isBanned(addr)) {
|
||||
this.logger.debug('Ignoring banned leech (%s).', addr.hostname);
|
||||
if (this.hosts.isBanned(host)) {
|
||||
this.logger.debug('Ignoring banned leech (%s).', host);
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
// Some kind of weird port collision
|
||||
// between inbound ports and outbound ports.
|
||||
if (this.peers.get(addr)) {
|
||||
this.logger.debug('Port collision (%s).', addr.hostname);
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
host = IP.hostname(host, socket.remotePort);
|
||||
|
||||
assert(!this.peers.get(host), 'Port collision.');
|
||||
|
||||
this.addInbound(socket);
|
||||
};
|
||||
@ -610,10 +606,7 @@ Pool.prototype.addLoader = function addLoader() {
|
||||
|
||||
addr = this.hosts.getHost();
|
||||
|
||||
if (this.peers.get(addr))
|
||||
return;
|
||||
|
||||
peer = this.peers.get(addr);
|
||||
peer = this.peers.get(addr.hostname);
|
||||
|
||||
if (peer) {
|
||||
this.setLoader(peer);
|
||||
@ -1524,7 +1517,7 @@ Pool.prototype.addOutbound = function addOutbound() {
|
||||
|
||||
addr = this.hosts.getHost();
|
||||
|
||||
if (this.peers.get(addr))
|
||||
if (this.peers.get(addr.hostname))
|
||||
return;
|
||||
|
||||
peer = this.createPeer(addr.port, addr.host);
|
||||
@ -1930,57 +1923,16 @@ Pool.prototype.setFeeRate = function setFeeRate(rate) {
|
||||
peer.sendFeeRate(rate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Increase peer's ban score.
|
||||
* @param {Peer} peer
|
||||
* @param {Number} score
|
||||
* @returns {Boolean} Whether the peer was banned.
|
||||
*/
|
||||
|
||||
Pool.prototype.increaseBan = function increaseBan(peer, score) {
|
||||
peer.banScore += score;
|
||||
|
||||
if (peer.banScore >= constants.BAN_SCORE) {
|
||||
this.logger.debug('Ban threshold exceeded (%s).', peer.hostname);
|
||||
this.ban(peer);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Ban a peer.
|
||||
* @param {NetAddress} addr
|
||||
* @param {Peer} peer
|
||||
*/
|
||||
|
||||
Pool.prototype.ban = function ban(addr) {
|
||||
var peer = this.peers.get(addr);
|
||||
|
||||
this.logger.debug('Banning peer (%s).', addr.hostname);
|
||||
this.hosts.ban(addr);
|
||||
|
||||
if (peer)
|
||||
peer.destroy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Unban a peer.
|
||||
* @param {String|NetAddress} addr
|
||||
*/
|
||||
|
||||
Pool.prototype.unban = function unban(addr) {
|
||||
this.hosts.unban(addr);
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether the host is banned.
|
||||
* @param {NetAddress} addr
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Pool.prototype.isBanned = function isBanned(addr) {
|
||||
return this.hosts.isBanned(addr);
|
||||
Pool.prototype.ban = function ban(peer) {
|
||||
this.logger.debug('Banning peer (%s).', peer.hostname);
|
||||
this.hosts.ban(peer.host);
|
||||
this.hosts.remove(peer.hostname);
|
||||
peer.destroy();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1988,14 +1940,10 @@ Pool.prototype.isBanned = function isBanned(addr) {
|
||||
* @param {Peer} peer
|
||||
*/
|
||||
|
||||
Pool.prototype.ignore = function ignore(addr) {
|
||||
var peer = this.peers.get(addr);
|
||||
|
||||
this.logger.debug('Ignoring peer (%s).', addr.hostname);
|
||||
this.hosts.ignore(addr);
|
||||
|
||||
if (peer)
|
||||
peer.destroy();
|
||||
Pool.prototype.ignore = function ignore(peer) {
|
||||
this.logger.debug('Ignoring peer (%s).', peer.hostname);
|
||||
this.hosts.ignore(peer.hostname);
|
||||
peer.destroy();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2129,8 +2077,21 @@ PeerList.prototype.repurpose = function repurpose(peer) {
|
||||
this.load = peer;
|
||||
};
|
||||
|
||||
PeerList.prototype.get = function get(addr) {
|
||||
return this.map[addr.hostname];
|
||||
PeerList.prototype.get = function get(hostname) {
|
||||
return this.map[hostname];
|
||||
};
|
||||
|
||||
PeerList.prototype.getByHost = function getByHost(host) {
|
||||
var peers = [];
|
||||
var peer;
|
||||
|
||||
for (peer = this.list.head; peer; peer = peer.next) {
|
||||
if (peer.host !== host)
|
||||
continue;
|
||||
peers.push(peer);
|
||||
}
|
||||
|
||||
return peers;
|
||||
};
|
||||
|
||||
PeerList.prototype.destroy = function destroy() {
|
||||
@ -2156,7 +2117,6 @@ PeerList.prototype.destroy = function destroy() {
|
||||
function HostList(pool) {
|
||||
this.network = pool.network;
|
||||
this.logger = pool.logger;
|
||||
this.maxOutbound = pool.maxOutbound;
|
||||
this.proxyServer = pool.proxyServer;
|
||||
this.list = new List();
|
||||
this.seeds = [];
|
||||
@ -2242,55 +2202,54 @@ HostList.prototype.add = function add(addr) {
|
||||
|
||||
/**
|
||||
* Remove host from host list.
|
||||
* @param {NetAddress} addr
|
||||
* @param {String} hostname
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
HostList.prototype.remove = function remove(addr) {
|
||||
var item = this.map[addr.hostname];
|
||||
HostList.prototype.remove = function remove(hostname) {
|
||||
var addr = this.map[hostname];
|
||||
|
||||
if (!item)
|
||||
if (!addr)
|
||||
return;
|
||||
|
||||
assert(this.list.remove(item));
|
||||
delete this.map[item.hostname];
|
||||
assert(this.list.remove(addr));
|
||||
delete this.map[addr.hostname];
|
||||
|
||||
return item;
|
||||
return addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark a peer as banned.
|
||||
* @param {NetAddress} addr
|
||||
* @param {String} host
|
||||
*/
|
||||
|
||||
HostList.prototype.ban = function ban(addr) {
|
||||
this.banned[addr.host] = util.now();
|
||||
return this.remove(addr);
|
||||
HostList.prototype.ban = function ban(host) {
|
||||
this.banned[host] = util.now();
|
||||
};
|
||||
|
||||
/**
|
||||
* Unban host.
|
||||
* @param {NetAddress} addr
|
||||
* @param {String} host
|
||||
*/
|
||||
|
||||
HostList.prototype.unban = function unban(addr) {
|
||||
delete this.banned[addr.host];
|
||||
HostList.prototype.unban = function unban(host) {
|
||||
delete this.banned[host];
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether the host is banned.
|
||||
* @param {NetAddress} addr
|
||||
* @param {String} host
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
HostList.prototype.isBanned = function isBanned(addr) {
|
||||
var time = this.banned[addr.host];
|
||||
HostList.prototype.isBanned = function isBanned(host) {
|
||||
var time = this.banned[host];
|
||||
|
||||
if (time == null)
|
||||
return false;
|
||||
|
||||
if (util.now() > time + constants.BAN_TIME) {
|
||||
delete this.banned[addr.host];
|
||||
delete this.banned[host];
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2299,16 +2258,17 @@ HostList.prototype.isBanned = function isBanned(addr) {
|
||||
|
||||
/**
|
||||
* Ignore peer.
|
||||
* @param {NetAddress} addr
|
||||
* @param {String} hostname
|
||||
*/
|
||||
|
||||
HostList.prototype.ignore = function ignore(addr) {
|
||||
var item = this.map[addr.hostname];
|
||||
HostList.prototype.ignore = function ignore(hostname) {
|
||||
var addr = this.map[hostname];
|
||||
|
||||
if (!item)
|
||||
if (!addr)
|
||||
return;
|
||||
|
||||
this.list.remove(item);
|
||||
delete this.map[hostname];
|
||||
this.list.remove(addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -30,7 +30,7 @@ var ipv6Regex =
|
||||
*/
|
||||
|
||||
IP.parseHost = function parseHost(addr, fallback) {
|
||||
var parts, host, port, version;
|
||||
var parts, host, port, version, hostname;
|
||||
|
||||
assert(typeof addr === 'string');
|
||||
|
||||
@ -94,7 +94,14 @@ IP.parseHost = function parseHost(addr, fallback) {
|
||||
if (version !== -1)
|
||||
host = IP.normalize(host);
|
||||
|
||||
return new Address(host, port, version);
|
||||
hostname = host;
|
||||
|
||||
if (version === 6)
|
||||
hostname = '[' + hostname + ']';
|
||||
|
||||
hostname += ':' + port;
|
||||
|
||||
return new Address(host, port, version, hostname);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -445,8 +452,9 @@ IP.loopback = function(family) {
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function Address(host, port, version) {
|
||||
function Address(host, port, version, hostname) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.version = version;
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user