fix ipv4/ipv6 address parsing and writing

This commit is contained in:
Manuel Araoz 2015-02-06 13:29:16 -03:00
parent 2489750913
commit 7119fad398
2 changed files with 53 additions and 40 deletions

View File

@ -39,7 +39,7 @@ var txHash = {
describe('Integration with ' + network.name + ' bitcoind', function() { describe('Integration with ' + network.name + ' bitcoind', function() {
this.timeout(15000); this.timeout(15000);
it.only('handshakes', function(cb) { it('handshakes', function(cb) {
var peer = new Peer('localhost', network); var peer = new Peer('localhost', network);
peer.once('version', function(m) { peer.once('version', function(m) {
m.version.should.be.above(70000); m.version.should.be.above(70000);
@ -84,11 +84,9 @@ describe('Integration with ' + network.name + ' bitcoind', function() {
}); });
}); });
}); });
it.only('handles addr', function(cb) { it('handles addr', function(cb) {
connect(function(peer) { connect(function(peer) {
peer.once('addr', function(message) { peer.once('addr', function(message) {
console.log(message.serialize(network).toString('hex'));
console.log(message.getPayload().toString('hex'));
message.addresses.forEach(function(address) { message.addresses.forEach(function(address) {
// console.log(address.ip.v4 + ':' + address.port); // console.log(address.ip.v4 + ':' + address.port);
(address.time instanceof Date).should.equal(true); (address.time instanceof Date).should.equal(true);

View File

@ -254,28 +254,17 @@ Version.prototype.fromBuffer = function(payload) {
*/ */
this.relay = !!parser.readUInt8(); this.relay = !!parser.readUInt8();
console.log(this);
$.checkState(parser.finished()); $.checkState(parser.finished());
return this; return this;
}; };
Version.writeAddr = function(addr, parser) {
if (_.isUndefined(addr)) {
parser.pad(26);
return;
}
parser.word64le(addr.services);
parser.put(addr.ip);
parser.word16be(addr.port);
};
Version.prototype.getPayload = function() { Version.prototype.getPayload = function() {
var put = new Put(); var put = new Put();
put.word32le(this.version); put.word32le(this.version);
put.word64le(1); // services put.word64le(1); // services
put.word64le(Math.round(new Date().getTime() / 1000)); // timestamp put.word64le(Math.round(new Date().getTime() / 1000)); // timestamp
Version.writeAddr(this.addr_me, put); Addresses.writeAddr(this.addr_me, put);
Version.writeAddr(this.addr_you, put); Addresses.writeAddr(this.addr_you, put);
put.put(this.nonce); put.put(this.nonce);
put.varint(this.subversion.length); put.varint(this.subversion.length);
put.put(new Buffer(this.subversion, 'ascii')); put.put(new Buffer(this.subversion, 'ascii'));
@ -475,26 +464,58 @@ function Addresses(addresses) {
} }
util.inherits(Addresses, Message); util.inherits(Addresses, Message);
Addresses.writeAddr = function(addr, put) {
if (_.isUndefined(addr)) {
put.pad(26);
return;
}
put.word64le(addr.services);
Addresses.writeIP(addr.ip, put);
put.word16be(addr.port);
};
Addresses.writeIP = function(ip, put) {
$.checkArgument(ip.v6, 'Need ipv6 to write IP');
var words = ip.v6.split(':').map(function(s) {
return new Buffer(s, 'hex');
});
for (var i = 0; i < words.length; i++) {
var word = words[i];
put.put(word);
}
};
// http://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses
Addresses.parseIP = function(parser) { Addresses.parseIP = function(parser) {
// parse the ipv6 to a string
var ipv6 = []; var ipv6 = [];
for (var a = 0; a < 6; a++) { var ipv4 = [];
ipv6.push(parser.read(2).toString('hex')); for (var a = 0; a < 8; a++) {
var word = parser.read(2);
ipv6.push(word.toString('hex'));
if (a >= 6) {
ipv4.push(word[0]);
ipv4.push(word[1]);
}
} }
ipv6 = ipv6.join(':'); ipv6 = ipv6.join(':');
// parse the ipv4 to a string
var ipv4 = [];
for (var b = 0; b < 4; b++) {
ipv4.push(parser.read(1)[0]);
}
ipv4 = ipv4.join('.'); ipv4 = ipv4.join('.');
return { return {
v6: ipv6, v6: ipv6,
v4: ipv4 v4: ipv4
}; };
}; };
Addresses.parseAddr = function(parser) {
var services = parser.readUInt64LEBN();
var ip = Addresses.parseIP(parser);
var port = parser.readUInt16BE();
return {
services: services,
ip: ip,
port: port
};
};
Addresses.prototype.fromBuffer = function(payload) { Addresses.prototype.fromBuffer = function(payload) {
var parser = new BufferReader(payload); var parser = new BufferReader(payload);
@ -503,18 +524,12 @@ Addresses.prototype.fromBuffer = function(payload) {
this.addresses = []; this.addresses = [];
for (var i = 0; i < addrCount; i++) { for (var i = 0; i < addrCount; i++) {
// TODO: Time actually depends on the version of the other peer (>=31402) // TODO: Time actually depends on the version of the other peer (>=31402)
var time = new Date(parser.readUInt32LE() * 1000); var time = new Date(parser.readUInt32LE() * 1000);
var services = parser.readUInt64LEBN();
var ip = Addresses.parseIP(parser);
var port = parser.readUInt16BE();
this.addresses.push({ var addr = Addresses.parseAddr(parser);
time: time, addr.time = time;
services: services,
ip: ip, this.addresses.push(addr);
port: port
});
} }
$.checkState(parser.finished()); $.checkState(parser.finished());
@ -526,10 +541,10 @@ Addresses.prototype.getPayload = function() {
put.varint(this.addresses.length); put.varint(this.addresses.length);
for (var i = 0; i < this.addresses.length; i++) { for (var i = 0; i < this.addresses.length; i++) {
put.word32le(this.addresses[i].time); var addr = this.addresses[i];
put.word64le(this.addresses[i].services); put.word32le(addr.time);
put.put(this.addresses[i].ip); Addresses.writeAddr(addr, put);
put.word16be(this.addresses[i].port); break;
} }
return put.buffer(); return put.buffer();