API fixes

This commit is contained in:
Kagami Hiiragi 2015-01-16 21:36:57 +03:00
parent 8fa539c61b
commit 3e9f3a62a6
2 changed files with 61 additions and 27 deletions

View File

@ -23,9 +23,9 @@ exports.version = {
NONCE: new Buffer("20bde0a3355dad78", "hex"), NONCE: new Buffer("20bde0a3355dad78", "hex"),
/** /**
* Decode `version` payload. * Decode `version` message payload.
* NOTE: `nonce` is copied. * NOTE: `nonce` is copied.
* @param {Buffer} buf - `version` payload * @param {Buffer} buf - Message payload
* @return {Object} Decoded `version` structure. * @return {Object} Decoded `version` structure.
*/ */
decode: function(buf) { decode: function(buf) {
@ -60,9 +60,9 @@ exports.version = {
}, },
/** /**
* Encode `version` payload. * Encode `version` message payload.
* @param {Object} opts - Version options * @param {Object} opts - Version options
* @return {Buffer} Encoded `version` payload. * @return {Buffer} Encoded payload.
*/ */
encode: function(opts) { encode: function(opts) {
// Deal with default options. // Deal with default options.
@ -107,8 +107,8 @@ exports.version = {
*/ */
exports.addr = { exports.addr = {
/** /**
* Decode `addr` payload. * Decode `addr` message payload.
* @param {Buffer} buf - `addr` payload * @param {Buffer} buf - Message payload
* @return {Object} Decoded `addr` structure. * @return {Object} Decoded `addr` structure.
*/ */
decode: function(buf) { decode: function(buf) {
@ -130,9 +130,9 @@ exports.addr = {
}, },
/** /**
* Encode `addr` payload. * Encode `addr` message payload.
* @param {Object[]} addrs - Network addresses * @param {Object[]} addrs - Network addresses
* @return {Buffer} Encoded `addr` payload. * @return {Buffer} Encoded payload.
*/ */
encode: function(addrs) { encode: function(addrs) {
assert(addrs.length <= 1000, "Too many address entires"); assert(addrs.length <= 1000, "Too many address entires");
@ -150,8 +150,8 @@ exports.addr = {
*/ */
var inv = exports.inv = { var inv = exports.inv = {
/** /**
* Decode `inv` payload. * Decode `inv` message payload.
* @param {Buffer} buf - `inv` payload * @param {Buffer} buf - Message payload
* @return {Object} Decoded `inv` structure. * @return {Object} Decoded `inv` structure.
*/ */
decode: function(buf) { decode: function(buf) {
@ -173,9 +173,9 @@ var inv = exports.inv = {
}, },
/** /**
* Encode `inv` payload. * Encode `inv` message payload.
* @param {Buffer[]} inventory - Inventory vector list (encoded) * @param {Buffer[]} inventory - Inventory vector list (encoded)
* @return {Buffer} Encoded `inv` payload. * @return {Buffer} Encoded payload.
*/ */
encode: function(inventory) { encode: function(inventory) {
assert(inventory.length <= 50000, "Too many inventory entires"); assert(inventory.length <= 50000, "Too many inventory entires");
@ -216,8 +216,8 @@ var error = exports.error = {
FATAL: 2, FATAL: 2,
/** /**
* Decode `error` payload. * Decode `error` message payload.
* @param {Buffer} buf - `error` payload * @param {Buffer} buf - Message payload
* @return {Object} Decoded `error` structure. * @return {Object} Decoded `error` structure.
*/ */
decode: function(buf) { decode: function(buf) {
@ -243,9 +243,9 @@ var error = exports.error = {
}, },
/** /**
* Encode `error` payload. * Encode `error` message payload.
* @param {Object} opts - Error options * @param {Object} opts - Error options
* @return {Buffer} Encoded `error` payload. * @return {Buffer} Encoded payload.
*/ */
encode: function(opts) { encode: function(opts) {
var fatal = opts.fatal || error.WARNING; var fatal = opts.fatal || error.WARNING;
@ -265,44 +265,66 @@ var error = exports.error = {
* `object` message. An `object` is a message which is shared throughout * `object` message. An `object` is a message which is shared throughout
* a stream. It is the only message which propagates; all others are * a stream. It is the only message which propagates; all others are
* only between two nodes. * only between two nodes.
* NOTE: You shouldn't use `encode` and `decode` methods directly.
* Instead, get type of the object and encode/decode it with appropriate
* function from `objects` module.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#object} * @see {@link https://bitmessage.org/wiki/Protocol_specification#object}
* @namespace * @namespace
*/ */
exports.object = { exports.object = {
// Known types.
GETPUBKEY: 0,
PUBKEY: 1,
MSG: 2,
BROADCAST: 3,
/** /**
* Decode `object` payload. * Returns type of the `object` message if we can parse it. Per spec
* NOTE: `nonce` and `payload` are copied. * we should still relay unknown objects.
* @param {Buffer} buf - `object` payload * @param {Buffer} buf - Message payload
* @return {?number} Object type.
*/
getType: function(buf) {
// Per v3 spec object starts with nonce (8 bytes), expiresTime (8
// bytes) and objectType (4 bytes). So we need only first 20 bytes
// to read the type.
if (buf.length >= 20) {
return buf.readUInt32BE(16, true);
}
},
/**
* Decode `object` message payload.
* NOTE: `nonce` is copied, `payload` references input buffer.
* @param {Buffer} buf - Message payload
* @return {Object} Decoded `object` structure. * @return {Object} Decoded `object` structure.
*/ */
decode: function(buf) { decode: function(buf) {
// 8 + 8 + 4 + (1+) + (1+) // 8 + 8 + 4 + (1+) + (1+)
assert(buf.length >= 22, "Buffer is too small"); assert(buf.length >= 22, "object message payload is too small");
var nonce = new Buffer(8); var nonce = new Buffer(8);
buf.copy(nonce, 0, 0, 8); buf.copy(nonce, 0, 0, 8);
var expiresTime = util.readTimestamp64BE(buf.slice(8, 16)); var expiresTime = util.readTimestamp64BE(buf.slice(8, 16));
var ttl = expiresTime - util.tnow(); var ttl = expiresTime - util.tnow();
assert(ttl >= -3600, "Object expired more than a hour ago"); assert(ttl >= -3600, "Object expired more than a hour ago");
assert(ttl <= 2430000, "expiresTime is too far in the future"); assert(ttl <= 2430000, "expiresTime is too far in the future");
var type = buf.readUInt32BE(16); var type = buf.readUInt32BE(16, true);
var decodedVersion = structs.var_int.decode(buf.slice(20)); var decodedVersion = structs.var_int.decode(buf.slice(20));
var decodedStream = structs.var_int.decode(decodedVersion.rest); var decodedStream = structs.var_int.decode(decodedVersion.rest);
var payload = new Buffer(decodedStream.rest.length);
decodedStream.rest.copy(payload);
return { return {
nonce: nonce, nonce: nonce,
ttl: ttl, ttl: ttl,
type: type, type: type,
version: decodedVersion.value, version: decodedVersion.value,
stream: decodedStream.value, stream: decodedStream.value,
payload: payload, payload: decodedStream.rest,
}; };
}, },
/** /**
* Encode `object` payload. * Encode `object` message payload.
* @param {Object} opts - Object options * @param {Object} opts - Object options
* @return {Buffer} Encoded `object` payload. * @return {Buffer} Encoded payload.
*/ */
encode: function(opts) { encode: function(opts) {
assert(opts.nonce.length === 8, "Bad nonce"); assert(opts.nonce.length === 8, "Bad nonce");

12
test.js
View File

@ -410,6 +410,18 @@ describe("Message types", function() {
payload: Buffer("test"), payload: Buffer("test"),
})).to.throw(Error); })).to.throw(Error);
}); });
it("should return type of the object", function() {
var encoded = object.encode({
nonce: Buffer(8),
ttl: 100,
type: object.BROADCAST,
version: 1,
payload: Buffer("test"),
});
expect(object.getType(encoded)).to.equal(3);
expect(object.decode(encoded).type).to.equal(3);
});
}); });
}); });