peer: handle address timestamp better.

Signed-off-by: Fedor Indutny <fedor@indutny.com>
This commit is contained in:
Christopher Jeffrey 2014-05-19 19:34:01 -05:00 committed by Fedor Indutny
parent a0c2f66169
commit 44fab2b58a
4 changed files with 36 additions and 39 deletions

View File

@ -27,6 +27,7 @@ function Peer(pool, createSocket, options) {
this.version = null; this.version = null;
this.destroyed = false; this.destroyed = false;
this.ack = false; this.ack = false;
this.ts = null;
this.options = options || {}; this.options = options || {};
if (this.options.backoff) { if (this.options.backoff) {
@ -69,6 +70,9 @@ module.exports = Peer;
Peer.prototype._init = function init() { Peer.prototype._init = function init() {
var self = this; var self = this;
this.socket.once('connect', function() {
self.ts = Date.now() / 1000 | 0;
});
this.socket.once('error', function(err) { this.socket.once('error', function(err) {
self._error(err); self._error(err);
}); });
@ -99,6 +103,7 @@ Peer.prototype._init = function init() {
return self._error(err); return self._error(err);
self.ack = true; self.ack = true;
self.emit('ack'); self.emit('ack');
self.ts = Date.now() / 1000 | 0;
}); });
}; };
@ -314,13 +319,19 @@ Peer.prototype._handleGetData = function handleGetData(items) {
}; };
Peer.prototype._handleAddr = function handleAddr(addrs) { Peer.prototype._handleAddr = function handleAddr(addrs) {
var now = Date.now();
addrs.forEach(function(addr) { addrs.forEach(function(addr) {
// bitcoind does this for some reason:
if (addr.ts <= 100000000 || addr.ts > now + 10 * 60)
addr.ts = now - 5 * 24 * 60 * 60;
this.emit('addr', { this.emit('addr', {
date: new Date(addr.date * 1000), date: new Date(addr.ts * 1000),
network: addr.network, ts: addr.ts,
address: addr.ipv4, service: addr.service,
ipv4: addr.ipv4, ipv4: addr.ipv4,
ipv6: addr.ipv6, ipv6: addr.ipv6,
address: addr.ipv4,
address6: addr.ipv6,
port: addr.port, port: addr.port,
host: addr.ipv4 + ':' + addr.port, host: addr.ipv4 + ':' + addr.port,
host6: '[' + addr.ipv6 + ']:' + addr.port host6: '[' + addr.ipv6 + ']:' + addr.port
@ -352,7 +363,8 @@ Peer.prototype._handleGetAddr = function handleGetAddr() {
return; return;
return { return {
host: peer.socket.remoteAddress, host: peer.socket.remoteAddress,
port: peer.socket.remotePort || 8333 port: peer.socket.remotePort || 8333,
ts: peer.ts
}; };
}).filter(function(peer) { }).filter(function(peer) {
if (!peer || ~used.indexOf(peer.host)) if (!peer || ~used.indexOf(peer.host))
@ -366,11 +378,12 @@ Peer.prototype._handleGetAddr = function handleGetAddr() {
ipv4: ver === 4 ? ip : '127.0.0.1', ipv4: ver === 4 ? ip : '127.0.0.1',
ipv6: ver === 6 ? ip : '0000:0000:0000:0000:0000:0000:0000:ffff', ipv6: ver === 6 ? ip : '0000:0000:0000:0000:0000:0000:0000:ffff',
port: peer.port, port: peer.port,
ts: peer.ts,
ver: ver ver: ver
}; };
}); });
peers = peers.map(function(peer) { var addrs = peers.map(function(peer) {
if (peer.ver === 6) { if (peer.ver === 6) {
while (peer.ipv6.split(':').length < 8) while (peer.ipv6.split(':').length < 8)
peer.ipv6 = '0000:' + peer.ipv6; peer.ipv6 = '0000:' + peer.ipv6;
@ -387,7 +400,7 @@ Peer.prototype._handleGetAddr = function handleGetAddr() {
return peer; return peer;
}).filter(Boolean); }).filter(Boolean);
return this._write(this.framer.addr(peers)); return this._write(this.framer.addr(addrs));
}; };
Peer.prototype._handleInv = function handleInv(items) { Peer.prototype._handleInv = function handleInv(items) {

View File

@ -327,6 +327,7 @@ Framer.prototype.addr = function addr(peers) {
var i = 0; var i = 0;
var c = 0; var c = 0;
var peer; var peer;
var start = (Date.now() / 1000 | 0) - process.uptime();
// count // count
c += varint(p, peers.length, c); c += varint(p, peers.length, c);
@ -334,8 +335,8 @@ Framer.prototype.addr = function addr(peers) {
for (; i < peers.length; i++) { for (; i < peers.length; i++) {
peer = peers[i]; peer = peers[i];
// date // timestamp
c += utils.writeU32(p, Date.now() / 1000 | 0, c); c += utils.writeU32(p, peer.ts || start, c);
// NODE_NETWORK service // NODE_NETWORK service
c += utils.writeU64(p, 1, c); c += utils.writeU64(p, 1, c);

View File

@ -356,7 +356,7 @@ Parser.prototype.parseAddr = function parseAddr(p) {
return this._error('Invalid addr size'); return this._error('Invalid addr size');
var addrs = []; var addrs = [];
var len, off, count, date, network, ipv4, ipv6, port, i; var len, off, count, ts, service, ipv4, ipv6, port, i;
// count // count
len = readIntv(p, 0); len = readIntv(p, 0);
@ -365,11 +365,11 @@ Parser.prototype.parseAddr = function parseAddr(p) {
p = p.slice(off); p = p.slice(off);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
// date - LE // ts - LE
date = utils.readU32(p, 0); ts = utils.readU32(p, 0);
// NODE_NETWORK service - LE // NODE_NETWORK service - LE
network = utils.readU64(p, 4); service = utils.readU64(p, 4);
// ipv6 - BE // ipv6 - BE
ipv6 = utils.toHex(p.slice(12, 24)); ipv6 = utils.toHex(p.slice(12, 24));
@ -386,8 +386,8 @@ Parser.prototype.parseAddr = function parseAddr(p) {
port = utils.readU16BE(p, 28); port = utils.readU16BE(p, 28);
addrs.push({ addrs.push({
date: date, ts: ts,
network: network, service: service,
ipv6: ipv6, ipv6: ipv6,
ipv4: ipv4, ipv4: ipv4,
port: port port: port

View File

@ -34,12 +34,14 @@ describe('Protocol', function() {
{ {
ipv6: '0000:0000:0000:0000:0000:0000:0000:ffff', ipv6: '0000:0000:0000:0000:0000:0000:0000:ffff',
ipv4: '127.0.0.1', ipv4: '127.0.0.1',
port: 8333 port: 8333,
ts: Date.now() / 1000 | 0
}, },
{ {
ipv6: '0000:0000:0000:0000:0000:7f00:0001:ffff', ipv6: '0000:0000:0000:0000:0000:7f00:0001:ffff',
ipv4: '10.0.0.1', ipv4: '10.0.0.1',
port: 18333 port: 18333,
ts: Date.now() / 1000 | 0
} }
]; ];
@ -54,37 +56,18 @@ describe('Protocol', function() {
addr._ipv6 = '::' + addr._ipv6.split(':').slice(2).join(':'); addr._ipv6 = '::' + addr._ipv6.split(':').slice(2).join(':');
}); });
packetTest('addr', peers, function(payload) { packetTest('addr', peers, function(payload) {
// XXX Legacy
if (!parser.parseAddr) {
var addrs = [];
bcoin.peer.prototype._handleAddr.call({
emit: function(_, obj) {
addrs.push(obj);
}
}, payload);
payload = addrs;
payload.forEach(function(addr) {
addr.date = addr.date.getTime() / 1000 | 0;
delete addr.address;
delete addr.host;
delete addr.host6;
addr.ipv6 = '::' + addr.ipv6;
});
}
assert.equal(typeof payload.length, 'number'); assert.equal(typeof payload.length, 'number');
assert.equal(payload.length, 2); assert.equal(payload.length, 2);
assert.equal(typeof payload[0].date, 'number'); assert.equal(typeof payload[0].ts, 'number');
assert.equal(payload[0].network, 1); assert.equal(payload[0].service, 1);
assert.equal(payload[0].ipv6, peers[0]._ipv6); assert.equal(payload[0].ipv6, peers[0]._ipv6);
assert.equal(payload[0].ipv4, peers[0]._ipv4); assert.equal(payload[0].ipv4, peers[0]._ipv4);
assert.equal(payload[0].port, peers[0].port); assert.equal(payload[0].port, peers[0].port);
assert.equal(typeof payload[1].date, 'number'); assert.equal(typeof payload[1].ts, 'number');
assert.equal(payload[1].network, 1); assert.equal(payload[1].service, 1);
assert.equal(payload[1].ipv6, peers[1]._ipv6); assert.equal(payload[1].ipv6, peers[1]._ipv6);
assert.equal(payload[1].ipv4, peers[1]._ipv4); assert.equal(payload[1].ipv4, peers[1]._ipv4);
assert.equal(payload[1].port, peers[1].port); assert.equal(payload[1].port, peers[1].port);