peer: use list for request queue.

This commit is contained in:
Christopher Jeffrey 2016-12-16 14:02:06 -08:00
parent 463ebd9bd3
commit 7971e56765
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
3 changed files with 60 additions and 71 deletions

View File

@ -547,21 +547,21 @@ function parseType(type) {
if (/form-urlencoded/i.test(type)) if (/form-urlencoded/i.test(type))
return 'form'; return 'form';
if (/text\/plain/i.test(type))
return 'text';
if (/\/x?html/i.test(type)) if (/\/x?html/i.test(type))
return 'html'; return 'html';
if (/text\/plain/i.test(type))
return 'text';
return 'binary'; return 'binary';
} }
function getType(type) { function getType(type) {
switch (type) { switch (type) {
case 'form':
return 'application/x-www-form-urlencoded; charset=utf-8';
case 'json': case 'json':
return 'application/json; charset=utf-8'; return 'application/json; charset=utf-8';
case 'form':
return 'application/x-www-form-urlencoded; charset=utf-8';
case 'html': case 'html':
return 'text/html; charset=utf-8'; return 'text/html; charset=utf-8';
case 'text': case 'text':

View File

@ -821,7 +821,7 @@ Peer.prototype.sendFeeRate = function sendFeeRate(rate) {
*/ */
Peer.prototype.destroy = function destroy() { Peer.prototype.destroy = function destroy() {
var i, j, keys, cmd, queue, hash; var i, j, keys, cmd, queue, entry, hash;
if (this.destroyed) if (this.destroyed)
return; return;
@ -860,16 +860,17 @@ Peer.prototype.destroy = function destroy() {
for (i = 0; i < keys.length; i++) { for (i = 0; i < keys.length; i++) {
cmd = keys[i]; cmd = keys[i];
queue = this.requestMap[cmd]; queue = this.requestMap[cmd];
for (entry = queue.head; entry; entry = entry.next)
for (j = 0; j < queue.length; j++) entry.stop();
queue[j].destroy(); delete this.requestMap[cmd];
} }
keys = Object.keys(this.compactBlocks); keys = Object.keys(this.compactBlocks);
for (i = 0; i < keys.length; i++) { for (i = 0; i < keys.length; i++) {
hash = keys[i]; hash = keys[i];
this.compactBlocks[hash].destroy(); entry = this.compactBlocks[hash];
entry.destroy();
} }
this.emit('close'); this.emit('close');
@ -1024,7 +1025,7 @@ Peer.prototype.request = function request(cmd) {
entry = new RequestEntry(self, cmd, resolve, reject); entry = new RequestEntry(self, cmd, resolve, reject);
if (!self.requestMap[cmd]) if (!self.requestMap[cmd])
self.requestMap[cmd] = []; self.requestMap[cmd] = new List();
self.requestMap[cmd].push(entry); self.requestMap[cmd].push(entry);
}); });
@ -1039,27 +1040,19 @@ Peer.prototype.request = function request(cmd) {
Peer.prototype.response = function response(cmd, payload) { Peer.prototype.response = function response(cmd, payload) {
var queue = this.requestMap[cmd]; var queue = this.requestMap[cmd];
var entry, res; var entry;
if (!queue) if (!queue)
return false; return false;
entry = queue[0]; entry = queue.shift();
assert(entry);
if (!entry) if (queue.size === 0)
return false;
res = entry.resolve(payload);
if (res === false)
return false;
queue.shift();
if (queue.length === 0)
delete this.requestMap[cmd]; delete this.requestMap[cmd];
entry.destroy(); entry.stop();
entry.resolve(payload);
return true; return true;
}; };
@ -1260,7 +1253,7 @@ Peer.prototype.fire = function fire(cmd, payload) {
Peer.prototype.handleFilterLoad = co(function* handleFilterLoad(packet) { Peer.prototype.handleFilterLoad = co(function* handleFilterLoad(packet) {
if (!packet.isWithinConstraints()) { if (!packet.isWithinConstraints()) {
this.setMisbehavior(100); this.increaseBan(100);
return; return;
} }
@ -1278,7 +1271,7 @@ Peer.prototype.handleFilterAdd = co(function* handleFilterAdd(packet) {
var data = packet.data; var data = packet.data;
if (data.length > constants.script.MAX_PUSH) { if (data.length > constants.script.MAX_PUSH) {
this.setMisbehavior(100); this.increaseBan(100);
return; return;
} }
@ -1329,7 +1322,7 @@ Peer.prototype.handleFeeFilter = co(function* handleFeeFilter(packet) {
var rate = packet.rate; var rate = packet.rate;
if (!(rate >= 0 && rate <= constants.MAX_MONEY)) { if (!(rate >= 0 && rate <= constants.MAX_MONEY)) {
this.setMisbehavior(100); this.increaseBan(100);
return; return;
} }
@ -2040,7 +2033,7 @@ Peer.prototype.handleInv = co(function* handleInv(packet) {
var i, item; var i, item;
if (items.length > 50000) { if (items.length > 50000) {
this.setMisbehavior(100); this.increaseBan(100);
return; return;
} }
@ -2093,7 +2086,7 @@ Peer.prototype.handleHeaders = co(function* handleHeaders(packet) {
headers.length, this.hostname); headers.length, this.hostname);
if (headers.length > 2000) { if (headers.length > 2000) {
this.setMisbehavior(100); this.increaseBan(100);
return; return;
} }
@ -2406,7 +2399,7 @@ Peer.prototype.handleGetBlockTxn = co(function* handleGetBlockTxn(packet) {
this.logger.debug( this.logger.debug(
'Peer sent getblocktxn for non-existent block (%s).', 'Peer sent getblocktxn for non-existent block (%s).',
this.hostname); this.hostname);
this.setMisbehavior(100); this.increaseBan(100);
return; return;
} }
@ -2446,7 +2439,7 @@ Peer.prototype.handleBlockTxn = co(function* handleBlockTxn(packet) {
delete this.compactBlocks[res.hash]; delete this.compactBlocks[res.hash];
if (!block.fillMissing(res)) { if (!block.fillMissing(res)) {
this.setMisbehavior(100); this.increaseBan(100);
this.logger.warning('Peer sent non-full blocktxn (%s).', this.hostname); this.logger.warning('Peer sent non-full blocktxn (%s).', this.hostname);
return; return;
} }
@ -2598,22 +2591,13 @@ Peer.prototype.isMisbehaving = function isMisbehaving() {
return this.pool.hosts.isMisbehaving(this); 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. * Increase banscore on peer.
* @param {Number} score * @param {Number} score
*/ */
Peer.prototype.setMisbehavior = function setMisbehavior(score) { Peer.prototype.increaseBan = function increaseBan(score) {
return this.pool.setMisbehavior(this, 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) { Peer.prototype.reject = function reject(obj, code, reason, score) {
this.sendReject(code, reason, obj); this.sendReject(code, reason, obj);
if (score > 0) if (score > 0)
this.setMisbehavior(score); this.increaseBan(score);
}; };
/** /**
@ -2759,27 +2743,26 @@ function RequestEntry(peer, cmd, resolve, reject) {
this.cmd = cmd; this.cmd = cmd;
this.resolve = resolve; this.resolve = resolve;
this.reject = reject; this.reject = reject;
this.id = RequestEntry.uid++;
this.onTimeout = this._onTimeout.bind(this); this.onTimeout = this._onTimeout.bind(this);
this.timeout = setTimeout(this.onTimeout, this.peer.requestTimeout); this.timeout = setTimeout(this.onTimeout, this.peer.requestTimeout);
this.prev = null;
this.next = null;
} }
RequestEntry.uid = 0;
RequestEntry.prototype._onTimeout = function _onTimeout() { RequestEntry.prototype._onTimeout = function _onTimeout() {
var queue = this.peer.requestMap[this.cmd]; var queue = this.peer.requestMap[this.cmd];
if (!queue) if (!queue)
return; return;
if (util.binaryRemove(queue, this, compare)) { if (queue.remove(this)) {
if (queue.length === 0) if (queue.size === 0)
delete this.peer.requestMap[this.cmd]; delete this.peer.requestMap[this.cmd];
this.reject(new Error('Timed out: ' + this.cmd)); this.reject(new Error('Timed out: ' + this.cmd));
} }
}; };
RequestEntry.prototype.destroy = function destroy() { RequestEntry.prototype.stop = function stop() {
if (this.timeout != null) { if (this.timeout != null) {
clearTimeout(this.timeout); clearTimeout(this.timeout);
this.timeout = null; this.timeout = null;

View File

@ -807,7 +807,7 @@ Pool.prototype._handleHeaders = co(function* handleHeaders(headers, peer) {
hash = header.hash('hex'); hash = header.hash('hex');
if (last && header.prevBlock !== last) { if (last && header.prevBlock !== last) {
peer.setMisbehavior(100); peer.increaseBan(100);
throw new Error('Bad header chain.'); throw new Error('Bad header chain.');
} }
@ -983,7 +983,7 @@ Pool.prototype.handleBlock = co(function* handleBlock(block, peer) {
if (err.reason === 'bad-prevblk') { if (err.reason === 'bad-prevblk') {
if (this.options.headers) { if (this.options.headers) {
peer.setMisbehavior(10); peer.increaseBan(10);
throw err; throw err;
} }
this.logger.debug('Peer sent an orphan block. Resolving.'); 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); this.logger.warning('Peer sent a phony alert packet (%s).', peer.hostname);
// Let's look at it because why not? // Let's look at it because why not?
this.logger.debug(alert); this.logger.debug(alert);
peer.setMisbehavior(100); peer.increaseBan(100);
return; return;
} }
@ -1356,7 +1356,7 @@ Pool.prototype.handleAlert = function handleAlert(alert, peer) {
&& alert.statusBar === 'URGENT: Alert key compromised, upgrade required')) { && alert.statusBar === 'URGENT: Alert key compromised, upgrade required')) {
this.logger.warning('Misuse of last alert ID (%s).', peer.hostname); this.logger.warning('Misuse of last alert ID (%s).', peer.hostname);
this.logger.debug(alert); this.logger.debug(alert);
peer.setMisbehavior(100); peer.increaseBan(100);
return; 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('The Japanese government sent an alert packet.');
this.logger.warning('Here is their IP: %s.', peer.hostname); this.logger.warning('Here is their IP: %s.', peer.hostname);
this.logger.info(alert); this.logger.info(alert);
peer.setMisbehavior(100); peer.increaseBan(100);
return; return;
} }
@ -1466,7 +1466,7 @@ Pool.prototype.addInbound = function addInbound(socket) {
peer = this.acceptPeer(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); this.peers.add(peer);
@ -1889,7 +1889,7 @@ Pool.prototype.setFeeRate = function setFeeRate(rate) {
* @returns {Boolean} Whether the peer was banned. * @returns {Boolean} Whether the peer was banned.
*/ */
Pool.prototype.setMisbehavior = function setMisbehavior(peer, score) { Pool.prototype.increaseBan = function increaseBan(peer, score) {
peer.banScore += score; peer.banScore += score;
if (peer.banScore >= constants.BAN_SCORE) { if (peer.banScore >= constants.BAN_SCORE) {
@ -1986,7 +1986,7 @@ Pool.prototype.getIP = co(function* getIP() {
*/ */
Pool.prototype.getIP2 = co(function* getIP2() { Pool.prototype.getIP2 = co(function* getIP2() {
var res, ip; var res, match, ip;
if (request.unsupported) if (request.unsupported)
throw new Error('Could not find IP.'); throw new Error('Could not find IP.');
@ -1998,12 +1998,17 @@ Pool.prototype.getIP2 = co(function* getIP2() {
timeout: 3000 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.'); 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) { HostList.prototype.isMisbehaving = function isMisbehaving(addr) {
var time = this.misbehaving[addr.host]; var time = this.misbehaving[addr.host];
if (time != null) { if (time == null)
if (util.now() > time + constants.BAN_TIME) { return false;
delete this.misbehaving[addr.host];
return false; if (util.now() > time + constants.BAN_TIME) {
} delete this.misbehaving[addr.host];
return true; return false;
} }
return false; return true;
}; };
/** /**
@ -2285,8 +2290,8 @@ HostList.prototype.addSeed = function addSeed(hostname) {
}; };
/** /**
* Populate from seed. * Discover hosts from seeds.
* @param {String} seed * @returns {Promise}
*/ */
HostList.prototype.discover = co(function* discover() { HostList.prototype.discover = co(function* discover() {
@ -2304,7 +2309,8 @@ HostList.prototype.discover = co(function* discover() {
/** /**
* Populate from seed. * Populate from seed.
* @param {String} seed * @param {Object} seed
* @returns {Promise}
*/ */
HostList.prototype.populate = co(function* populate(seed) { HostList.prototype.populate = co(function* populate(seed) {