better ping system.

This commit is contained in:
Christopher Jeffrey 2016-05-19 22:22:09 -07:00
parent bd3d17ef53
commit e97f1d0477
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 88 additions and 29 deletions

View File

@ -55,6 +55,9 @@ var constants = bcoin.protocol.constants;
* @property {BN} challenge - Local nonce. * @property {BN} challenge - Local nonce.
* @property {Number} lastPong - Timestamp for last `pong` * @property {Number} lastPong - Timestamp for last `pong`
* received (unix time). * received (unix time).
* @property {Number} lastPing - Timestamp for last `ping`
* sent (unix time).
* @property {Number} minPing - Lowest ping time seen.
* @property {String} id - Peer's uid. * @property {String} id - Peer's uid.
* @property {Number} banScore * @property {Number} banScore
* @emits Peer#ack * @emits Peer#ack
@ -98,8 +101,10 @@ function Peer(pool, options) {
this.localNonce = utils.nonce(); this.localNonce = utils.nonce();
this.filterRate = -1; this.filterRate = -1;
this.challenge = utils.nonce(); this.challenge = null;
this.lastPong = 0; this.lastPong = -1;
this.lastPing = -1;
this.minPing = -1;
this.banScore = 0; this.banScore = 0;
@ -132,7 +137,7 @@ function Peer(pool, options) {
this.ping = { this.ping = {
timer: null, timer: null,
interval: this.options.pingInterval || 30000 interval: this.options.pingInterval || 120000
}; };
this.queue = { this.queue = {
@ -186,13 +191,6 @@ Peer.prototype._init = function init() {
self._error(err); self._error(err);
}); });
this.ping.timer = setInterval(function() {
// self.challenge = utils.nonce();
self.write(self.framer.ping({
nonce: self.challenge
}));
}, this.ping.interval);
this.request('verack', function(err, payload) { this.request('verack', function(err, payload) {
if (err) { if (err) {
self._error(err); self._error(err);
@ -204,6 +202,10 @@ Peer.prototype._init = function init() {
self.emit('ack'); self.emit('ack');
self.ts = utils.now(); self.ts = utils.now();
self.ping.timer = setInterval(function() {
self.sendPing();
}, self.ping.interval);
if (self.options.headers) { if (self.options.headers) {
if (self.version && self.version.version > 70012) if (self.version && self.version.version > 70012)
self.write(self.framer.sendHeaders()); self.write(self.framer.sendHeaders());
@ -259,12 +261,12 @@ Peer.prototype.createSocket = function createSocket(port, host) {
} }
bcoin.debug( bcoin.debug(
'Connecting to %s:%d (priority=%s).', 'Connecting to %s (priority=%s).',
hostname, this.priority); hostname, this.priority);
socket.once('connect', function() { socket.once('connect', function() {
bcoin.debug( bcoin.debug(
'Connected to %s:%d (priority=%s).', 'Connected to %s (priority=%s).',
hostname, self.priority); hostname, self.priority);
}); });
@ -314,6 +316,32 @@ Peer.prototype.sendInv = function sendInv(items) {
this.write(this.framer.inv(items)); this.write(this.framer.inv(items));
}; };
/**
* Send a `ping` packet.
*/
Peer.prototype.sendPing = function sendPing() {
if (!this.version)
return;
if (this.version.version <= 60000) {
this.write(this.framer.packet('ping', new Buffer([])));
return;
}
if (this.challenge) {
bcoin.debug('Peer has not responded to ping (%s).', this.hostname);
return;
}
this.lastPing = utils.ms();
this.challenge = utils.nonce();
this.write(this.framer.ping({
nonce: this.challenge
}));
};
/** /**
* Test whether an is being watched by the peer. * Test whether an is being watched by the peer.
* @param {BroadcastItem|TX} item * @param {BroadcastItem|TX} item
@ -367,8 +395,10 @@ Peer.prototype.destroy = function destroy() {
this.socket = null; this.socket = null;
this.emit('close'); this.emit('close');
clearInterval(this.ping.timer); if (this.ping.timer) {
this.ping.timer = null; clearInterval(this.ping.timer);
this.ping.timer = null;
}
Object.keys(this.requests.map).forEach(function(cmd) { Object.keys(this.requests.map).forEach(function(cmd) {
var queue = this.requests.map[cmd]; var queue = this.requests.map[cmd];
@ -1220,19 +1250,40 @@ Peer.prototype._handleAddr = function handleAddr(addrs) {
}; };
Peer.prototype._handlePing = function handlePing(data) { Peer.prototype._handlePing = function handlePing(data) {
this.write(this.framer.pong({ this.write(this.framer.pong(data));
nonce: data.nonce this.emit('ping', this.minPing);
}));
this.emit('ping', data);
}; };
Peer.prototype._handlePong = function handlePong(data) { Peer.prototype._handlePong = function handlePong(data) {
if (!this.challenge || this.challenge.cmp(data.nonce) !== 0) var now = utils.ms();
return this.emit('pong', false);
this.lastPong = utils.now(); if (!this.challenge) {
bcoin.debug('Peer sent an unsolicited pong (%s).', this.hostname);
return;
}
return this.emit('pong', true); if (data.nonce.cmp(this.challenge) !== 0) {
if (data.nonce.cmpn(0) === 0) {
bcoin.debug('Peer sent a zero nonce (%s).', this.hostname);
this.challenge = null;
return;
}
bcoin.debug('Peer sent the wrong nonce (%s).', this.hostname);
return;
}
if (now >= this.lastPing) {
this.lastPong = now;
if (this.minPing === -1)
this.minPing = now - this.lastPing;
this.minPing = Math.min(this.minPing, now - this.lastPing);
} else {
bcoin.debug('Timing mismatch (what?) (%s).', this.hostname);
}
this.challenge = null;
this.emit('pong', this.minPing);
}; };
Peer.prototype._handleGetAddr = function handleGetAddr() { Peer.prototype._handleGetAddr = function handleGetAddr() {
@ -1445,6 +1496,7 @@ Peer.prototype.inspect = function inspect() {
+ ' id=' + this.id + ' id=' + this.id
+ ' connected=' + this.connected + ' connected=' + this.connected
+ ' host=' + this.hostname + ' host=' + this.hostname
+ ' ping=' + this.minPing
+ '>'; + '>';
}; };

View File

@ -868,17 +868,15 @@ utils.parseHost = function parseHost(addr) {
/** /**
* Concatenate a host and port. * Concatenate a host and port.
* @param {Seed} seed * @param {String} host
* @param {Number} port
* @returns {String} * @returns {String}
*/ */
utils.hostname = function hostname(seed) { utils.hostname = function hostname(host, port) {
var host = seed.host;
if (utils.isIP(host) === 6) if (utils.isIP(host) === 6)
host = '[' + host + ']'; host = '[' + host + ']';
return host + ':' + port;
return host + ':' + seed.port;
}; };
/** /**
@ -1283,7 +1281,16 @@ utils.testTarget = function testTarget(hash, target) {
*/ */
utils.now = function now() { utils.now = function now() {
return +new Date() / 1000 | 0; return Math.floor(+new Date() / 1000);
};
/**
* Get current time in unix time (milliseconds).
* @returns {Number}
*/
utils.ms = function ms() {
return +new Date();
}; };
/** /**