ip and version.
This commit is contained in:
parent
ae41e11ff3
commit
e8cf4ea8be
@ -244,10 +244,32 @@ Peer.prototype._init = function init() {
|
||||
|
||||
// Say hello.
|
||||
this.write(this.framer.version({
|
||||
version: constants.VERSION,
|
||||
services: constants.LOCAL_SERVICES,
|
||||
ts: bcoin.now(),
|
||||
remote: {},
|
||||
local: {
|
||||
services: constants.LOCAL_SERVICES,
|
||||
host: this.pool.host,
|
||||
port: this.pool.port
|
||||
},
|
||||
nonce: this.pool.localNonce,
|
||||
agent: constants.USER_AGENT,
|
||||
height: this.chain.height,
|
||||
relay: this.options.relay,
|
||||
nonce: this.pool.localNonce
|
||||
}));
|
||||
|
||||
// Advertise our address.
|
||||
if (this.pool.host !== '0.0.0.0'
|
||||
&& !this.pool.options.selfish
|
||||
&& this.pool.server) {
|
||||
this.write(this.framer.addr([{
|
||||
ts: utils.now() - (process.uptime() | 0),
|
||||
services: constants.LOCAL_SERVICES,
|
||||
host: this.pool.host,
|
||||
port: this.pool.port
|
||||
}]));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1302,26 +1324,23 @@ Peer.prototype._handleGetData = function handleGetData(items) {
|
||||
|
||||
Peer.prototype._handleAddr = function handleAddr(addrs) {
|
||||
var now = utils.now();
|
||||
var i, addr, ts, host;
|
||||
var i, addr, ts;
|
||||
|
||||
for (i = 0; i < addrs.length; i++) {
|
||||
addr = addrs[i];
|
||||
|
||||
ts = addr.ts;
|
||||
host = addr.ipv4 !== '0.0.0.0'
|
||||
? addr.ipv4
|
||||
: addr.ipv6;
|
||||
|
||||
if (ts <= 100000000 || ts > now + 10 * 60)
|
||||
ts = now - 5 * 24 * 60 * 60;
|
||||
|
||||
this.addrFilter.add(host, 'ascii');
|
||||
this.addrFilter.add(addr.host, 'ascii');
|
||||
|
||||
this.emit('addr', {
|
||||
version: addr.version,
|
||||
ts: ts,
|
||||
services: addr.services,
|
||||
host: host,
|
||||
host: addr.host,
|
||||
port: addr.port || this.network.port
|
||||
});
|
||||
}
|
||||
@ -1375,7 +1394,7 @@ Peer.prototype._handleGetAddr = function handleGetAddr() {
|
||||
var hosts = {};
|
||||
var items = [];
|
||||
var ts = utils.now() - (process.uptime() | 0);
|
||||
var i, seed, version, peer;
|
||||
var i, seed, peer;
|
||||
|
||||
if (this.pool.options.selfish)
|
||||
return;
|
||||
@ -1383,9 +1402,8 @@ Peer.prototype._handleGetAddr = function handleGetAddr() {
|
||||
for (i = 0; i < this.pool.seeds.length; i++) {
|
||||
seed = utils.parseHost(this.pool.seeds[i]);
|
||||
seed = this.pool.getPeer(seed.host) || seed;
|
||||
version = utils.isIP(seed.host);
|
||||
|
||||
if (!version)
|
||||
if (!utils.isIP(seed.host))
|
||||
continue;
|
||||
|
||||
if (hosts[seed.host])
|
||||
@ -1397,11 +1415,9 @@ Peer.prototype._handleGetAddr = function handleGetAddr() {
|
||||
continue;
|
||||
|
||||
items.push({
|
||||
network: this.network,
|
||||
ts: seed.ts || ts,
|
||||
services: seed.version ? seed.version.services : null,
|
||||
ipv4: version === 4 ? seed.host : null,
|
||||
ipv6: version === 6 ? seed.host : null,
|
||||
services: seed.version ? seed.version.services : 0,
|
||||
host: seed.host,
|
||||
port: seed.port || this.network.port
|
||||
});
|
||||
|
||||
|
||||
@ -108,6 +108,8 @@ function Pool(options) {
|
||||
this.seeds = [];
|
||||
this.hosts = {};
|
||||
this.setSeeds([]);
|
||||
this.host = '0.0.0.0';
|
||||
this.port = this.network.port;
|
||||
|
||||
this.server = null;
|
||||
this.destroyed = false;
|
||||
@ -194,20 +196,7 @@ function Pool(options) {
|
||||
interval: options.invInterval || 3000
|
||||
};
|
||||
|
||||
function done(err) {
|
||||
if (err)
|
||||
return self.emit('error', err);
|
||||
|
||||
self.loaded = true;
|
||||
self.emit('open');
|
||||
|
||||
self._init();
|
||||
}
|
||||
|
||||
if (this.mempool)
|
||||
this.mempool.open(done);
|
||||
else
|
||||
this.chain.open(done);
|
||||
this._init();
|
||||
}
|
||||
|
||||
utils.inherits(Pool, EventEmitter);
|
||||
@ -316,6 +305,29 @@ Pool.prototype._init = function _init() {
|
||||
self.emit('full');
|
||||
bcoin.debug('Chain is fully synced (height=%d).', self.chain.height);
|
||||
});
|
||||
|
||||
function done(err) {
|
||||
if (err)
|
||||
return self.emit('error', err);
|
||||
|
||||
self.loaded = true;
|
||||
self.emit('open');
|
||||
}
|
||||
|
||||
this.getIP(function(err, ip) {
|
||||
if (err)
|
||||
bcoin.error(err);
|
||||
|
||||
if (ip) {
|
||||
self.host = ip;
|
||||
bcoin.debug('External IP found: %s.', ip);
|
||||
}
|
||||
|
||||
if (self.mempool)
|
||||
self.mempool.open(done);
|
||||
else
|
||||
self.chain.open(done);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2088,6 +2100,62 @@ Pool.prototype.reject = function reject(peer, obj, code, reason, score) {
|
||||
peer.setMisbehavior(score);
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempt to retrieve external IP from icanhazip.com.
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Pool.prototype.getIP = function getIP(callback) {
|
||||
var self = this;
|
||||
var request = require('./http/request');
|
||||
var ip;
|
||||
|
||||
if (utils.isBrowser)
|
||||
return callback(new Error('Could not find IP.'));
|
||||
|
||||
request({
|
||||
method: 'GET',
|
||||
uri: 'http://icanhazip.com',
|
||||
expect: 'text'
|
||||
}, function(err, res, body) {
|
||||
if (err)
|
||||
return self.getIP2(callback);
|
||||
|
||||
ip = body.trim();
|
||||
|
||||
if (!utils.isIP(ip))
|
||||
return self.getIP2(callback);
|
||||
|
||||
return callback(null, ip);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempt to retrieve external IP from dyndns.org.
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Pool.prototype.getIP2 = function getIP2(callback) {
|
||||
var request = require('./http/request');
|
||||
var ip;
|
||||
|
||||
request({
|
||||
method: 'GET',
|
||||
uri: 'http://checkip.dyndns.org',
|
||||
expect: 'html'
|
||||
}, function(err, res, body) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
ip = /IP Address:\s*([0-9.:]+)/i.exec(body);
|
||||
|
||||
if (!ip || !utils.isIP(ip[1]))
|
||||
return callback(new Error('Could not find IP.'));
|
||||
|
||||
return callback(null, ip[1]);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents an in-flight block or transaction.
|
||||
* @exports LoadRequest
|
||||
|
||||
@ -17,8 +17,6 @@ var DUMMY = new Buffer([]);
|
||||
* @exports Framer
|
||||
* @constructor
|
||||
* @param {Object} options
|
||||
* @param {String} options.USER_AGENT - User agent string.
|
||||
* @property {Buffer} agent
|
||||
*/
|
||||
|
||||
function Framer(options) {
|
||||
@ -30,8 +28,6 @@ function Framer(options) {
|
||||
|
||||
this.options = options;
|
||||
this.network = bcoin.network.get(options.network);
|
||||
|
||||
this.agent = options.agent || constants.USER_AGENT;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,12 +90,6 @@ Framer.prototype.packet = function packet(cmd, payload, checksum) {
|
||||
*/
|
||||
|
||||
Framer.prototype.version = function version(options) {
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
options.agent = this.agent;
|
||||
options.network = this.network;
|
||||
|
||||
return this.packet('version', Framer.version(options));
|
||||
};
|
||||
|
||||
@ -409,7 +399,8 @@ Framer.prototype.addr = function addr(peers) {
|
||||
*/
|
||||
|
||||
Framer.prototype.alert = function alert(options) {
|
||||
return this.packet('alert', Framer.alert(options, this.network));
|
||||
options.network = this.network;
|
||||
return this.packet('alert', Framer.alert(options));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -432,7 +423,6 @@ Framer.prototype.feeFilter = function feeFilter(options) {
|
||||
|
||||
Framer.address = function address(data, full, writer) {
|
||||
var p = new BufferWriter(writer);
|
||||
var network = bcoin.network.get(data.network);
|
||||
|
||||
if (full) {
|
||||
if (!data.ts)
|
||||
@ -442,22 +432,8 @@ Framer.address = function address(data, full, writer) {
|
||||
}
|
||||
|
||||
p.writeU64(data.services || 0);
|
||||
|
||||
if (data.ipv6) {
|
||||
p.writeBytes(utils.ip2array(data.ipv6, 6));
|
||||
} else {
|
||||
// We don't have an ipv6 address: convert
|
||||
// ipv4 to ipv4-mapped ipv6 address.
|
||||
p.writeU32BE(0x00000000);
|
||||
p.writeU32BE(0x00000000);
|
||||
p.writeU32BE(0x0000ffff);
|
||||
if (data.ipv4)
|
||||
p.writeBytes(utils.ip2array(data.ipv4, 4));
|
||||
else
|
||||
p.writeU32BE(0x00000000);
|
||||
}
|
||||
|
||||
p.writeU16BE(data.port || network.port);
|
||||
p.writeBytes(utils.ip2array(data.host));
|
||||
p.writeU16BE(data.port || 0);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
@ -475,15 +451,13 @@ Framer.address = function address(data, full, writer) {
|
||||
Framer.version = function version(options, writer) {
|
||||
var p = new BufferWriter(writer);
|
||||
var agent = options.agent || constants.USER_AGENT;
|
||||
var services = options.services;
|
||||
var remote = options.remote || {};
|
||||
var local = options.local || {};
|
||||
var nonce = options.nonce;
|
||||
|
||||
if (local.network == null)
|
||||
local.network = options.network;
|
||||
|
||||
if (remote.network == null)
|
||||
remote.network = options.network;
|
||||
if (services == null)
|
||||
services = constants.LOCAL_SERVICES;
|
||||
|
||||
if (local.services == null)
|
||||
local.services = constants.LOCAL_SERVICES;
|
||||
@ -491,9 +465,9 @@ Framer.version = function version(options, writer) {
|
||||
if (!nonce)
|
||||
nonce = utils.nonce();
|
||||
|
||||
p.write32(constants.VERSION);
|
||||
p.writeU64(constants.LOCAL_SERVICES);
|
||||
p.write64(utils.now());
|
||||
p.write32(options.version || constants.VERSION);
|
||||
p.writeU64(services);
|
||||
p.write64(options.ts || bcoin.now());
|
||||
Framer.address(remote, false, p);
|
||||
Framer.address(local, false, p);
|
||||
p.writeU64(nonce);
|
||||
@ -1189,28 +1163,19 @@ Framer.reject = function reject(details, writer) {
|
||||
|
||||
/**
|
||||
* Create an addr packet (without a header).
|
||||
* @param {InvItem[]} peers
|
||||
* @param {NetworkAddress[]} hosts
|
||||
* @param {BufferWriter?} writer - A buffer writer to continue writing from.
|
||||
* @returns {Buffer} Returns a BufferWriter if `writer` was passed in.
|
||||
*/
|
||||
|
||||
Framer.addr = function addr(peers, writer) {
|
||||
Framer.addr = function addr(hosts, writer) {
|
||||
var p = new BufferWriter(writer);
|
||||
var i, peer;
|
||||
var i;
|
||||
|
||||
p.writeVarint(peers.length);
|
||||
p.writeVarint(hosts.length);
|
||||
|
||||
for (i = 0; i < peers.length; i++) {
|
||||
peer = peers[i];
|
||||
Framer.address({
|
||||
network: peer.network,
|
||||
ts: peer.ts,
|
||||
services: peer.services,
|
||||
ipv6: peer.ipv6,
|
||||
ipv4: peer.ipv4,
|
||||
port: peer.port
|
||||
}, true, p);
|
||||
}
|
||||
for (i = 0; i < hosts.length; i++)
|
||||
Framer.address(hosts[i], true, p);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
@ -1221,16 +1186,14 @@ Framer.addr = function addr(peers, writer) {
|
||||
/**
|
||||
* Create an alert packet (without a header).
|
||||
* @param {AlertPacket} data
|
||||
* @param {Network|NetworkType} network
|
||||
* @param {BufferWriter?} writer - A buffer writer to continue writing from.
|
||||
* @returns {Buffer} Returns a BufferWriter if `writer` was passed in.
|
||||
*/
|
||||
|
||||
Framer.alert = function alert(data, network, writer) {
|
||||
var p, i, payload;
|
||||
Framer.alert = function alert(data, writer) {
|
||||
var network = bcoin.network.get(data.network);
|
||||
var key = data.key;
|
||||
|
||||
network = bcoin.network.get(network);
|
||||
var p, i, payload;
|
||||
|
||||
if (!key && network.alertPrivateKey)
|
||||
key = network.alertPrivateKey;
|
||||
@ -1470,7 +1433,7 @@ Framer.filterClear = function filterClear() {
|
||||
* @returns {Buffer} Returns a BufferWriter if `writer` was passed in.
|
||||
*/
|
||||
|
||||
Framer.feeFilter = function feeFilter(data, network, writer) {
|
||||
Framer.feeFilter = function feeFilter(data, writer) {
|
||||
var p = new BufferWriter(writer);
|
||||
|
||||
p.write64(data.rate);
|
||||
|
||||
@ -1198,8 +1198,7 @@ Parser.parseAddress = function parseAddress(p, full) {
|
||||
return {
|
||||
ts: ts,
|
||||
services: services,
|
||||
ipv6: utils.array2ip(ip, 6),
|
||||
ipv4: utils.array2ip(ip, 4),
|
||||
host: utils.array2ip(ip),
|
||||
port: port
|
||||
};
|
||||
};
|
||||
|
||||
@ -258,8 +258,7 @@
|
||||
* @typedef {Object} NetworkAddress
|
||||
* @property {Number?} ts - Timestamp.
|
||||
* @property {Number?} services - Service bits.
|
||||
* @property {Buffer?} ipv4 - IPv4 address.
|
||||
* @property {Buffer?} ipv6 - IPv6 address.
|
||||
* @property {String?} host - IP address (IPv6 or IPv4).
|
||||
* @property {Number?} port - Port.
|
||||
* @global
|
||||
*/
|
||||
|
||||
@ -899,159 +899,104 @@ utils.isIP = function isIP(ip) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast an IPv6 or IPv4 to IPv4 or IPv6 respectively
|
||||
* (if possible using ipv4-mapped ipv6 addresses).
|
||||
* @param {Buffer} ip
|
||||
* @param {Number} version - 4 or 6.
|
||||
* @returns {Buffer} IP address.
|
||||
* Test whether a buffer is an ipv4-mapped ipv6 address.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
utils.ip2version = function ip2version(ip, version) {
|
||||
var b, i, j;
|
||||
utils.isMapped = function isMapped(ip, version) {
|
||||
var i;
|
||||
|
||||
assert(Buffer.isBuffer(ip));
|
||||
assert(version === 4 || version === 6, 'Bad IP version.');
|
||||
if (!Buffer.isBuffer(ip))
|
||||
return false;
|
||||
|
||||
if (version === 4) {
|
||||
// Check to see if this an
|
||||
// ipv4-mapped ipv6 address.
|
||||
if (ip.length > 4) {
|
||||
i = 0;
|
||||
while (ip[i] === 0)
|
||||
i++;
|
||||
|
||||
// Found an ipv4 address
|
||||
if (ip.length - i === 6 && ip[i] === 0xff && ip[i + 1] === 0xff)
|
||||
return utils.copy(ip.slice(-4));
|
||||
|
||||
// No ipv4 address
|
||||
return new Buffer([0, 0, 0, 0]);
|
||||
}
|
||||
|
||||
// Pad to 4 bytes
|
||||
if (ip.length < 4) {
|
||||
b = new Buffer(4);
|
||||
i = ip.length;
|
||||
j = b.length;
|
||||
b.fill(0);
|
||||
while (i)
|
||||
b[--j] = ip[--i];
|
||||
ip = b;
|
||||
}
|
||||
|
||||
return ip;
|
||||
for (i = 0; i < ip.length - 6; i++) {
|
||||
if (ip[i] !== 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (version === 6) {
|
||||
// Pad to 4 bytes
|
||||
if (ip.length < 4) {
|
||||
b = new Buffer(4);
|
||||
i = ip.length;
|
||||
j = b.length;
|
||||
b.fill(0);
|
||||
while (i)
|
||||
b[--j] = ip[--i];
|
||||
ip = b;
|
||||
}
|
||||
if (ip[10] !== 0xff && ip[11] !== 0xff)
|
||||
return false;
|
||||
|
||||
// Try to convert ipv4 address to
|
||||
// ipv4-mapped ipv6 address.
|
||||
if (ip.length === 4) {
|
||||
b = new Buffer(6);
|
||||
i = ip.length;
|
||||
j = b.length;
|
||||
b.fill(0xff);
|
||||
while (i)
|
||||
b[--j] = ip[--i];
|
||||
ip = b;
|
||||
}
|
||||
|
||||
// Pad to 16 bytes
|
||||
if (ip.length < 16) {
|
||||
b = new Buffer(16);
|
||||
i = ip.length;
|
||||
j = b.length;
|
||||
b.fill(0);
|
||||
while (i)
|
||||
b[--j] = ip[--i];
|
||||
ip = b;
|
||||
}
|
||||
|
||||
return ip;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert an IP string to a buffer.
|
||||
* @param {String} ip
|
||||
* @param {Number} version - 4 or 6.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
utils.ip2array = function ip2array(ip, version) {
|
||||
var type = utils.isIP(ip);
|
||||
var parts;
|
||||
utils.ip2array = function ip2array(ip) {
|
||||
var version, parts, out;
|
||||
|
||||
assert(version === 4 || version === 6, 'Bad IP version.');
|
||||
|
||||
if (type === 0) {
|
||||
if (!Buffer.isBuffer(ip))
|
||||
ip = new Buffer([0, 0, 0, 0]);
|
||||
} else if (type === 4) {
|
||||
parts = ip.split('.');
|
||||
ip = new Buffer(4);
|
||||
ip[0] = +parts[0];
|
||||
ip[1] = +parts[1];
|
||||
ip[2] = +parts[2];
|
||||
ip[3] = +parts[3];
|
||||
} else if (type === 6) {
|
||||
ip = new Buffer(ip.replace(/:/g, ''), 'hex');
|
||||
assert(ip.length <= 16);
|
||||
if (Buffer.isBuffer(ip)) {
|
||||
assert(ip.length === 16);
|
||||
return ip;
|
||||
}
|
||||
|
||||
return utils.ip2version(ip, version);
|
||||
version = utils.isIP(ip);
|
||||
|
||||
if (version === 0)
|
||||
return ip2array('0.0.0.0');
|
||||
|
||||
if (version === 4) {
|
||||
parts = ip.split('.');
|
||||
assert(parts.length === 4);
|
||||
out = new Buffer(16);
|
||||
out.fill(0);
|
||||
out[10] = 0xff;
|
||||
out[11] = 0xff;
|
||||
out[12] = +parts[0];
|
||||
out[13] = +parts[1];
|
||||
out[14] = +parts[2];
|
||||
out[15] = +parts[3];
|
||||
return out;
|
||||
}
|
||||
|
||||
if (version === 6) {
|
||||
ip = new Buffer(ip.replace(/:/g, ''), 'hex');
|
||||
assert(ip.length === 16);
|
||||
return ip;
|
||||
}
|
||||
|
||||
assert(false, 'Bad IP.');
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a buffer to an ip string.
|
||||
* @param {Buffer} ip
|
||||
* @param {Number} version - 4 or 6.
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
utils.array2ip = function array2ip(ip, version) {
|
||||
var out, i, hi, lo;
|
||||
utils.array2ip = function array2ip(ip) {
|
||||
var i, out, hi, lo;
|
||||
|
||||
if (!Buffer.isBuffer(ip)) {
|
||||
if (utils.isIP(ip))
|
||||
ip = utils.ip2array(ip, version);
|
||||
else
|
||||
ip = new Buffer([0, 0, 0, 0]);
|
||||
if (typeof ip === 'string') {
|
||||
assert(utils.isIP(ip) !== 0);
|
||||
return ip;
|
||||
}
|
||||
|
||||
assert(version === 4 || version === 6, 'Bad IP version.');
|
||||
assert(ip.length <= 16);
|
||||
if (!Buffer.isBuffer(ip))
|
||||
return '0.0.0.0';
|
||||
|
||||
ip = utils.ip2version(ip, version);
|
||||
assert(ip.length === 16);
|
||||
|
||||
if (version === 4)
|
||||
return ip[0] + '.' + ip[1] + '.' + ip[2] + '.' + ip[3];
|
||||
if (utils.isMapped(ip))
|
||||
return ip[12] + '.' + ip[13] + '.' + ip[14] + '.' + ip[15];
|
||||
|
||||
if (version === 6) {
|
||||
out = [];
|
||||
out = [];
|
||||
|
||||
for (i = 0; i < ip.length; i += 2) {
|
||||
hi = ip[i].toString(16);
|
||||
if (hi.length < 2)
|
||||
hi = '0' + hi;
|
||||
lo = ip[i + 1].toString(16);
|
||||
if (lo.length < 2)
|
||||
lo = '0' + lo;
|
||||
out.push(hi + lo);
|
||||
}
|
||||
|
||||
return out.join(':');
|
||||
for (i = 0; i < ip.length; i += 2) {
|
||||
hi = ip[i].toString(16);
|
||||
if (hi.length < 2)
|
||||
hi = '0' + hi;
|
||||
lo = ip[i + 1].toString(16);
|
||||
if (lo.length < 2)
|
||||
lo = '0' + lo;
|
||||
out.push(hi + lo);
|
||||
}
|
||||
|
||||
return out.join(':');
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user