From 7971e567653a19acb5bb8fae1c421fefe64cd9a8 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 16 Dec 2016 14:02:06 -0800 Subject: [PATCH] peer: use list for request queue. --- lib/http/request.js | 10 +++---- lib/net/peer.js | 73 +++++++++++++++++---------------------------- lib/net/pool.js | 48 ++++++++++++++++------------- 3 files changed, 60 insertions(+), 71 deletions(-) diff --git a/lib/http/request.js b/lib/http/request.js index 838ed224..a4d717a7 100644 --- a/lib/http/request.js +++ b/lib/http/request.js @@ -547,21 +547,21 @@ function parseType(type) { if (/form-urlencoded/i.test(type)) return 'form'; - if (/text\/plain/i.test(type)) - return 'text'; - if (/\/x?html/i.test(type)) return 'html'; + if (/text\/plain/i.test(type)) + return 'text'; + return 'binary'; } function getType(type) { switch (type) { - case 'form': - return 'application/x-www-form-urlencoded; charset=utf-8'; case 'json': return 'application/json; charset=utf-8'; + case 'form': + return 'application/x-www-form-urlencoded; charset=utf-8'; case 'html': return 'text/html; charset=utf-8'; case 'text': diff --git a/lib/net/peer.js b/lib/net/peer.js index a4d0fa27..b3fd95bd 100644 --- a/lib/net/peer.js +++ b/lib/net/peer.js @@ -821,7 +821,7 @@ Peer.prototype.sendFeeRate = function sendFeeRate(rate) { */ Peer.prototype.destroy = function destroy() { - var i, j, keys, cmd, queue, hash; + var i, j, keys, cmd, queue, entry, hash; if (this.destroyed) return; @@ -860,16 +860,17 @@ Peer.prototype.destroy = function destroy() { for (i = 0; i < keys.length; i++) { cmd = keys[i]; queue = this.requestMap[cmd]; - - for (j = 0; j < queue.length; j++) - queue[j].destroy(); + for (entry = queue.head; entry; entry = entry.next) + entry.stop(); + delete this.requestMap[cmd]; } keys = Object.keys(this.compactBlocks); for (i = 0; i < keys.length; i++) { hash = keys[i]; - this.compactBlocks[hash].destroy(); + entry = this.compactBlocks[hash]; + entry.destroy(); } this.emit('close'); @@ -1024,7 +1025,7 @@ Peer.prototype.request = function request(cmd) { entry = new RequestEntry(self, cmd, resolve, reject); if (!self.requestMap[cmd]) - self.requestMap[cmd] = []; + self.requestMap[cmd] = new List(); self.requestMap[cmd].push(entry); }); @@ -1039,27 +1040,19 @@ Peer.prototype.request = function request(cmd) { Peer.prototype.response = function response(cmd, payload) { var queue = this.requestMap[cmd]; - var entry, res; + var entry; if (!queue) return false; - entry = queue[0]; + entry = queue.shift(); + assert(entry); - if (!entry) - return false; - - res = entry.resolve(payload); - - if (res === false) - return false; - - queue.shift(); - - if (queue.length === 0) + if (queue.size === 0) delete this.requestMap[cmd]; - entry.destroy(); + entry.stop(); + entry.resolve(payload); return true; }; @@ -1260,7 +1253,7 @@ Peer.prototype.fire = function fire(cmd, payload) { Peer.prototype.handleFilterLoad = co(function* handleFilterLoad(packet) { if (!packet.isWithinConstraints()) { - this.setMisbehavior(100); + this.increaseBan(100); return; } @@ -1278,7 +1271,7 @@ Peer.prototype.handleFilterAdd = co(function* handleFilterAdd(packet) { var data = packet.data; if (data.length > constants.script.MAX_PUSH) { - this.setMisbehavior(100); + this.increaseBan(100); return; } @@ -1329,7 +1322,7 @@ Peer.prototype.handleFeeFilter = co(function* handleFeeFilter(packet) { var rate = packet.rate; if (!(rate >= 0 && rate <= constants.MAX_MONEY)) { - this.setMisbehavior(100); + this.increaseBan(100); return; } @@ -2040,7 +2033,7 @@ Peer.prototype.handleInv = co(function* handleInv(packet) { var i, item; if (items.length > 50000) { - this.setMisbehavior(100); + this.increaseBan(100); return; } @@ -2093,7 +2086,7 @@ Peer.prototype.handleHeaders = co(function* handleHeaders(packet) { headers.length, this.hostname); if (headers.length > 2000) { - this.setMisbehavior(100); + this.increaseBan(100); return; } @@ -2406,7 +2399,7 @@ Peer.prototype.handleGetBlockTxn = co(function* handleGetBlockTxn(packet) { this.logger.debug( 'Peer sent getblocktxn for non-existent block (%s).', this.hostname); - this.setMisbehavior(100); + this.increaseBan(100); return; } @@ -2446,7 +2439,7 @@ Peer.prototype.handleBlockTxn = co(function* handleBlockTxn(packet) { delete this.compactBlocks[res.hash]; if (!block.fillMissing(res)) { - this.setMisbehavior(100); + this.increaseBan(100); this.logger.warning('Peer sent non-full blocktxn (%s).', this.hostname); return; } @@ -2598,22 +2591,13 @@ Peer.prototype.isMisbehaving = function isMisbehaving() { return this.pool.hosts.isMisbehaving(this); }; -/** - * Check whether the peer is ignored. - * @returns {Boolean} - */ - -Peer.prototype.isIgnored = function isIgnored() { - return this.pool.hosts.isIgnored(this); -}; - /** * Increase banscore on peer. * @param {Number} score */ -Peer.prototype.setMisbehavior = function setMisbehavior(score) { - return this.pool.setMisbehavior(this, score); +Peer.prototype.increaseBan = function increaseBan(score) { + return this.pool.increaseBan(this, score); }; /** @@ -2636,7 +2620,7 @@ Peer.prototype.ignore = function ignore() { Peer.prototype.reject = function reject(obj, code, reason, score) { this.sendReject(code, reason, obj); if (score > 0) - this.setMisbehavior(score); + this.increaseBan(score); }; /** @@ -2759,27 +2743,26 @@ function RequestEntry(peer, cmd, resolve, reject) { this.cmd = cmd; this.resolve = resolve; this.reject = reject; - this.id = RequestEntry.uid++; this.onTimeout = this._onTimeout.bind(this); this.timeout = setTimeout(this.onTimeout, this.peer.requestTimeout); + this.prev = null; + this.next = null; } -RequestEntry.uid = 0; - RequestEntry.prototype._onTimeout = function _onTimeout() { var queue = this.peer.requestMap[this.cmd]; if (!queue) return; - if (util.binaryRemove(queue, this, compare)) { - if (queue.length === 0) + if (queue.remove(this)) { + if (queue.size === 0) delete this.peer.requestMap[this.cmd]; this.reject(new Error('Timed out: ' + this.cmd)); } }; -RequestEntry.prototype.destroy = function destroy() { +RequestEntry.prototype.stop = function stop() { if (this.timeout != null) { clearTimeout(this.timeout); this.timeout = null; diff --git a/lib/net/pool.js b/lib/net/pool.js index 72ede0fb..fee56399 100644 --- a/lib/net/pool.js +++ b/lib/net/pool.js @@ -807,7 +807,7 @@ Pool.prototype._handleHeaders = co(function* handleHeaders(headers, peer) { hash = header.hash('hex'); if (last && header.prevBlock !== last) { - peer.setMisbehavior(100); + peer.increaseBan(100); throw new Error('Bad header chain.'); } @@ -983,7 +983,7 @@ Pool.prototype.handleBlock = co(function* handleBlock(block, peer) { if (err.reason === 'bad-prevblk') { if (this.options.headers) { - peer.setMisbehavior(10); + peer.increaseBan(10); throw err; } this.logger.debug('Peer sent an orphan block. Resolving.'); @@ -1334,7 +1334,7 @@ Pool.prototype.handleAlert = function handleAlert(alert, peer) { this.logger.warning('Peer sent a phony alert packet (%s).', peer.hostname); // Let's look at it because why not? this.logger.debug(alert); - peer.setMisbehavior(100); + peer.increaseBan(100); return; } @@ -1356,7 +1356,7 @@ Pool.prototype.handleAlert = function handleAlert(alert, peer) { && alert.statusBar === 'URGENT: Alert key compromised, upgrade required')) { this.logger.warning('Misuse of last alert ID (%s).', peer.hostname); this.logger.debug(alert); - peer.setMisbehavior(100); + peer.increaseBan(100); return; } } @@ -1367,7 +1367,7 @@ Pool.prototype.handleAlert = function handleAlert(alert, peer) { this.logger.warning('The Japanese government sent an alert packet.'); this.logger.warning('Here is their IP: %s.', peer.hostname); this.logger.info(alert); - peer.setMisbehavior(100); + peer.increaseBan(100); return; } @@ -1466,7 +1466,7 @@ Pool.prototype.addInbound = function addInbound(socket) { peer = this.acceptPeer(socket); - this.logger.info('Added leech peer (%s).', peer.hostname); + this.logger.info('Added inbound peer (%s).', peer.hostname); this.peers.add(peer); @@ -1889,7 +1889,7 @@ Pool.prototype.setFeeRate = function setFeeRate(rate) { * @returns {Boolean} Whether the peer was banned. */ -Pool.prototype.setMisbehavior = function setMisbehavior(peer, score) { +Pool.prototype.increaseBan = function increaseBan(peer, score) { peer.banScore += score; if (peer.banScore >= constants.BAN_SCORE) { @@ -1986,7 +1986,7 @@ Pool.prototype.getIP = co(function* getIP() { */ Pool.prototype.getIP2 = co(function* getIP2() { - var res, ip; + var res, match, ip; if (request.unsupported) throw new Error('Could not find IP.'); @@ -1998,12 +1998,17 @@ Pool.prototype.getIP2 = co(function* getIP2() { timeout: 3000 }); - ip = /IP Address:\s*([0-9a-f.:]+)/i.exec(res.body); + match = /IP Address:\s*([0-9a-f.:]+)/i.exec(res.body); - if (!ip || IP.version(ip[1]) === -1) + if (!match) throw new Error('Could not find IP.'); - return IP.normalize(ip[1]); + ip = match[1]; + + if (IP.version(ip) === -1) + throw new Error('Could not parse IP.'); + + return IP.normalize(ip); }); /** @@ -2233,15 +2238,15 @@ HostList.prototype.unban = function unban(addr) { HostList.prototype.isMisbehaving = function isMisbehaving(addr) { var time = this.misbehaving[addr.host]; - if (time != null) { - if (util.now() > time + constants.BAN_TIME) { - delete this.misbehaving[addr.host]; - return false; - } - return true; + if (time == null) + return false; + + if (util.now() > time + constants.BAN_TIME) { + delete this.misbehaving[addr.host]; + return false; } - return false; + return true; }; /** @@ -2285,8 +2290,8 @@ HostList.prototype.addSeed = function addSeed(hostname) { }; /** - * Populate from seed. - * @param {String} seed + * Discover hosts from seeds. + * @returns {Promise} */ HostList.prototype.discover = co(function* discover() { @@ -2304,7 +2309,8 @@ HostList.prototype.discover = co(function* discover() { /** * Populate from seed. - * @param {String} seed + * @param {Object} seed + * @returns {Promise} */ HostList.prototype.populate = co(function* populate(seed) {