diff --git a/lib/http/rpc.js b/lib/http/rpc.js index ff0cec5c..58abae91 100644 --- a/lib/http/rpc.js +++ b/lib/http/rpc.js @@ -528,7 +528,7 @@ RPC.prototype.getpeerinfo = co(function* getpeerinfo(args, help) { lastrecv: peer.lastRecv / 1000 | 0, bytessent: peer.socket.bytesWritten, bytesrecv: peer.socket.bytesRead, - conntime: peer.ts !== 0 ? util.now() - peer.ts : 0, + conntime: peer.ts !== 0 ? (util.ms() - peer.ts) / 1000 | 0 : 0, timeoffset: offset, pingtime: peer.lastPong !== -1 ? (peer.lastPong - peer.lastPing) / 1000 diff --git a/lib/net/common.js b/lib/net/common.js index 4c7764df..99d424c7 100644 --- a/lib/net/common.js +++ b/lib/net/common.js @@ -37,6 +37,14 @@ exports.MIN_VERSION = 70001; exports.HEADERS_VERSION = 31800; +/** + * Minimum version for pong. + * @const {Number} + * @default + */ + +exports.PONG_VERSION = 60000; + /** * Minimum version for bip37. * @const {Number} diff --git a/lib/net/peer.js b/lib/net/peer.js index 9541fb12..e625632e 100644 --- a/lib/net/peer.js +++ b/lib/net/peer.js @@ -207,6 +207,14 @@ Peer.BLOCK_TIMEOUT = 120000; Peer.MAX_REQUESTS = 5000; +/** + * Generic timeout interval. + * @const {Number} + * @default + */ + +Peer.TIMEOUT_INTERVAL = 20 * 60000; + /** * Create inbound peer from socket. * @param {PeerOptions} options @@ -410,7 +418,7 @@ Peer.prototype.accept = function accept(socket) { this.address = NetAddress.fromSocket(socket, this.network); this.address.services = 0; - this.ts = util.now(); + this.ts = util.ms(); this.outbound = false; this.connected = true; @@ -434,7 +442,6 @@ Peer.prototype.connect = function connect(addr) { socket = this.options.createSocket(addr.port, addr.host); this.address = addr; - this.ts = util.now(); this.outbound = true; this.connected = false; @@ -526,7 +533,7 @@ Peer.prototype.initConnect = function initConnect() { } self.socket.once('connect', function() { - self.ts = util.now(); + self.ts = util.ms(); self.connected = true; self.emit('connect'); @@ -998,7 +1005,7 @@ Peer.prototype.sendPing = function sendPing() { if (!this.handshake) return; - if (this.version <= 60000) { + if (this.version <= common.PONG_VERSION) { this.send(new packets.PingPacket()); return; } @@ -1286,7 +1293,7 @@ Peer.prototype.fulfill = function fulfill(packet) { Peer.prototype.maybeTimeout = function maybeTimeout() { var keys = this.responseMap.keys(); var now = util.ms(); - var i, key, entry, name; + var i, key, entry, name, ts, mult; for (i = 0; i < keys.length; i++) { key = keys[i]; @@ -1327,14 +1334,44 @@ Peer.prototype.maybeTimeout = function maybeTimeout() { for (i = 0; i < keys.length; i++) { key = keys[i]; - entry = this.requestMap.get(key); - if (now > entry + Peer.BLOCK_TIMEOUT) { + ts = this.requestMap.get(key); + if (now > ts + Peer.BLOCK_TIMEOUT) { this.error('Peer is stalling (block).'); this.destroy(); return; } } } + + if (now > this.ts + 60000) { + assert(this.ts !== 0); + + if (this.lastRecv === 0 || this.lastSend === 0) { + this.error('Peer is stalling (no message).'); + this.destroy(); + return; + } + + if (now > this.lastSend + Peer.TIMEOUT_INTERVAL) { + this.error('Peer is stalling (send).'); + this.destroy(); + return; + } + + mult = this.version <= common.PONG_VERSION ? 4 : 1; + + if (now > this.lastRecv + Peer.TIMEOUT_INTERVAL * mult) { + this.error('Peer is stalling (recv).'); + this.destroy(); + return; + } + + if (this.challenge && now > this.lastPing + Peer.TIMEOUT_INTERVAL) { + this.error('Peer is stalling (ping).'); + this.destroy(); + return; + } + } }; /**