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