bitmessage-js/docs/messages.js.html
Kagami Hiiragi a0da866121 Publish docs
2015-01-31 14:54:23 +03:00

475 lines
15 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: messages.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: messages.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>/**
* Working with messages.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#Message_types}
* @see {@link https://bitmessage.org/wiki/Protocol_specification_v3#Message_types}
* @see {@link https://bitmessage.org/Bitmessage%20Technical%20Paper.pdf}
* @module bitmessage/messages
*/
// TODO(Kagami): Document object-like params.
"use strict";
var objectAssign = Object.assign || require("object-assign");
var assert = require("./_util").assert;
var structs = require("./structs");
var UserAgent = require("./user-agent");
var util = require("./_util");
var message = structs.message;
var ServicesBitfield = structs.ServicesBitfield;
/**
* Try to get command of the given encoded message.
* Note that this function doesn't do any validation because it is
* already provided by
* [message.decode]{@link module:bitmessage/structs.message.decode}
* routine. Normally you call this for each incoming message and then
* call decode function of the appropriate message handler.
* @param {Buffer} buf - Buffer that starts with encoded message
* @return {?string} Message's command if any.
*/
exports.getCommand = function(buf) {
if (buf.length &lt; 16) {
return;
}
var command = buf.slice(4, 16);
var firstNonNull = 0;
for (var i = 11; i >=0; i--) {
if (command[i] !== 0) {
firstNonNull = i + 1;
break;
}
}
return command.slice(0, firstNonNull).toString("ascii");
};
/**
* `version` message.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#version}
* @namespace
* @static
*/
var version = exports.version = {
/**
* Random nonce used to detect connections to self.
* @const {Buffer}
*/
NONCE: new Buffer("20bde0a3355dad78", "hex"),
/**
* Decode `version` message.
* NOTE: `nonce` is copied.
* @param {Buffer} buf - Message
* @return {Object} Decoded `version` structure.
*/
decode: function(buf) {
var decoded = message.decode(buf);
assert(decoded.command === "version", "Bad command");
return version.decodePayload(decoded.payload);
},
/**
* Decode `version` message payload.
* NOTE: `nonce` is copied.
* @param {Buffer} buf - Message payload
* @return {Object} Decoded `version` structure.
*/
decodePayload: function(buf) {
// 4 + 8 + 8 + 26 + 26 + 8 + (1+) + (1+)
assert(buf.length >= 82, "Buffer is too small");
var protoVersion = buf.readUInt32BE(0, true);
var services = ServicesBitfield(buf.slice(4, 12), {copy: true});
var time = util.readTime64BE(buf, 12);
var short = {short: true};
var addrRecv = structs.net_addr.decode(buf.slice(20, 46), short);
var addrFrom = structs.net_addr.decode(buf.slice(46, 72), short);
var nonce = new Buffer(8);
buf.copy(nonce, 0, 72, 80);
var decodedUa = UserAgent.decode(buf.slice(80));
var decodedStreamNumbers = structs.var_int_list.decode(decodedUa.rest);
return {
version: protoVersion,
services: services,
time: time,
remoteHost: addrRecv.host,
remotePort: addrRecv.port,
port: addrFrom.port,
nonce: nonce,
userAgent: decodedUa.str,
streamNumbers: decodedStreamNumbers.list,
// NOTE(Kagami): Real data length. It may be some gap between end
// of stream numbers list and end of payload:
// [payload..............[stream numbers]xxxx]
// We are currently ignoring that.
length: 80 + decodedUa.length + decodedStreamNumbers.length,
};
},
/**
* Encode `version` message.
* @param {Object} opts - Version options
* @return {Buffer} Encoded message.
*/
encode: function(opts) {
var payload = version.encodePayload(opts);
return message.encode("version", payload);
},
/**
* Encode `version` message payload.
* @param {Object} opts - Version options
* @return {Buffer} Encoded payload.
*/
encodePayload: function(opts) {
// Deal with default options.
var services = opts.services ||
ServicesBitfield().set(ServicesBitfield.NODE_NETWORK);
var time = opts.time || new Date();
var nonce = opts.nonce || version.NONCE;
assert(nonce.length === 8, "Bad nonce");
var userAgent = opts.userAgent || UserAgent.SELF;
var streamNumbers = opts.streamNumbers || [1];
// Start encoding.
var protoVersion = new Buffer(4);
protoVersion.writeUInt32BE(util.PROTOCOL_VERSION, 0);
var addrRecv = structs.net_addr.encode({
services: services,
host: opts.remoteHost,
port: opts.remotePort,
short: true,
});
var addrFrom = structs.net_addr.encode({
services: services,
host: "127.0.0.1",
port: opts.port,
short: true,
});
return Buffer.concat([
protoVersion,
services.buffer,
util.writeTime64BE(null, time),
addrRecv,
addrFrom,
nonce,
UserAgent.encode(userAgent),
structs.var_int_list.encode(streamNumbers),
]);
},
};
/**
* `addr` message. Provide information on known nodes of the network.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#addr}
* @namespace
* @static
*/
var addr = exports.addr = {
/**
* Decode `addr` message.
* @param {Buffer} buf - Message
* @return {Object} Decoded `addr` structure.
*/
decode: function(buf) {
var decoded = message.decode(buf);
assert(decoded.command === "addr", "Bad command");
return addr.decodePayload(decoded.payload);
},
/**
* Decode `addr` message payload.
* @param {Buffer} buf - Message payload
* @return {Object} Decoded `addr` structure.
*/
decodePayload: function(buf) {
var decoded = structs.var_int.decode(buf);
var listLength = decoded.value;
assert(listLength &lt;= 1000, "Too many address entires");
var length = decoded.length + listLength * 38;
assert(buf.length >= length, "Buffer is too small");
var rest = decoded.rest;
var addrs = new Array(listLength);
for (var i = 0; i &lt; listLength; i++) {
addrs[i] = structs.net_addr.decode(rest.slice(i*38, (i+1)*38));
}
return {
addrs: addrs,
// Real data length.
length: length,
};
},
/**
* Encode `addr` message.
* @param {Object[]} addrs - Network addresses
* @return {Buffer} Encoded message.
*/
encode: function(addrs) {
var payload = addr.encodePayload(addrs);
return message.encode("addr", payload);
},
/**
* Encode `addr` message payload.
* @param {Object[]} addrs - Network addresses
* @return {Buffer} Encoded payload.
*/
encodePayload: function(addrs) {
assert(addrs.length &lt;= 1000, "Too many address entires");
var addrsBuf = Buffer.concat(addrs.map(structs.net_addr.encode));
return Buffer.concat([structs.var_int.encode(addrs.length), addrsBuf]);
},
};
/**
* `inv` message. Allows a node to advertise its knowledge of one or
* more objects.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#inv}
* @namespace
* @static
*/
var inv = exports.inv = {
/**
* Decode `inv` message.
* @param {Buffer} buf - Message
* @return {Object} Decoded `inv` structure.
*/
decode: function(buf) {
var decoded = message.decode(buf);
assert(decoded.command === "inv", "Bad command");
return inv.decodePayload(decoded.payload);
},
/**
* Decode `inv` message payload.
* @param {Buffer} buf - Message payload
* @return {Object} Decoded `inv` structure.
*/
decodePayload: function(buf) {
var decoded = structs.var_int.decode(buf);
var listLength = decoded.value;
assert(listLength &lt;= 50000, "Too many inventory entires");
var length = decoded.length + listLength * 32;
assert(buf.length >= length, "Buffer is too small");
var rest = decoded.rest;
var inventory = new Array(listLength);
for (var i = 0; i &lt; listLength; i++) {
inventory[i] = rest.slice(i*32, (i+1)*32);
}
return {
inventory: inventory,
// Real data length.
length: length,
};
},
/**
* Encode `inv` message.
* @param {Buffer[]} inventory - Inventory vector list
* @return {Buffer} Encoded message.
*/
encode: function(inventory) {
var payload = inv.encodePayload(inventory);
return message.encode("inv", payload);
},
/**
* Encode `inv` message payload.
* @param {Buffer[]} inventory - Inventory vector list
* @return {Buffer} Encoded payload.
*/
encodePayload: function(inventory) {
assert(inventory.length &lt;= 50000, "Too many inventory entires");
var invBuf = Buffer.concat(inventory);
return Buffer.concat([structs.var_int.encode(inventory.length), invBuf]);
},
};
/**
* `getdata` message. `getdata` is used in response to an
* [inv]{@link module:bitmessage/messages.inv} message to retrieve the
* content of a specific object after filtering known elements.
* @see {@link https://bitmessage.org/wiki/Protocol_specification#getdata}
* @namespace
*/
exports.getdata = objectAssign({}, inv, {
/**
* Decode `getdata` message.
* @param {Buffer} buf - Message
* @return {Object} Decoded `getdata` structure.
* @memberof module:bitmessage/messages.getdata
*/
decode: function(buf) {
var decoded = message.decode(buf);
assert(decoded.command === "getdata", "Bad command");
return inv.decodePayload(decoded.payload);
},
/**
* Encode `getdata` message.
* @param {Buffer[]} inventory - Inventory vector list
* @return {Buffer} Encoded message.
* @memberof module:bitmessage/messages.getdata
*/
encode: function(inventory) {
var payload = inv.encodePayload(inventory);
return message.encode("getdata", payload);
},
/**
* Decode `getdata` message payload.
* @param {Buffer} buf - Message payload
* @return {Object} Decoded `inv` structure.
* @function decodePayload
* @memberof module:bitmessage/messages.getdata
*/
/**
* Encode `getdata` message payload.
* @param {Buffer[]} inventory - Inventory vector list
* @return {Buffer} Encoded payload.
* @function encodePayload
* @memberof module:bitmessage/messages.getdata
*/
});
/**
* `error` message.
* @see {@link https://bitmessage.org/wiki/Protocol_specification_v3#error}
* @namespace
* @static
*/
var error = exports.error = {
/**
* Just a warning.
* @constant {number}
*/
WARNING: 0,
/**
* It's an error, something was going wrong (e.g. an object got lost).
* @constant {number}
*/
ERROR: 1,
/**
* It's a fatal error. The node will drop the line for that error and
* maybe ban you for some time.
* @constant {number}
*/
FATAL: 2,
/**
* Decode `error` message.
* @param {Buffer} buf - Message
* @return {Object} Decoded `error` structure.
*/
decode: function(buf) {
var decoded = message.decode(buf);
assert(decoded.command === "error", "Bad command");
return error.decodePayload(decoded.payload);
},
/**
* Decode `error` message payload.
* @param {Buffer} buf - Message payload
* @return {Object} Decoded `error` structure.
*/
decodePayload: function(buf) {
assert(buf.length >= 4, "Buffer is too small");
var decodedFatal = structs.var_int.decode(buf);
var decodedBanTime = structs.var_int.decode(decodedFatal.rest);
var decodedVector = structs.var_str.decode(decodedBanTime.rest);
var decodedErrorText = structs.var_str.decode(decodedVector.rest);
var length = (
decodedFatal.length +
decodedBanTime.length +
decodedVector.length +
decodedErrorText.length
);
return {
fatal: decodedFatal.value,
banTime: decodedBanTime.value,
vector: decodedVector.str,
errorText: decodedErrorText.str,
// Real data length.
length: length,
};
},
/**
* Encode `error` message.
* @param {Object} opts - Error options
* @return {Buffer} Encoded message.
*/
encode: function(opts) {
var payload = error.encodePayload(opts);
return message.encode("error", payload);
},
/**
* Encode `error` message payload.
* @param {Object} opts - Error options
* @return {Buffer} Encoded payload.
*/
encodePayload: function(opts) {
var fatal = opts.fatal || error.WARNING;
var banTime = opts.banTime || 0;
var vector = opts.vector || "";
var errorText = opts.errorText || "";
return Buffer.concat([
structs.var_int.encode(fatal),
structs.var_int.encode(banTime),
structs.var_str.encode(vector),
structs.var_str.encode(errorText),
]);
},
};
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-bitmessage.html">bitmessage</a></li><li><a href="module-bitmessage_address.html">bitmessage/address</a></li><li><a href="module-bitmessage_crypto.html">bitmessage/crypto</a></li><li><a href="module-bitmessage_messages.html">bitmessage/messages</a></li><li><a href="module-bitmessage_objects.html">bitmessage/objects</a></li><li><a href="module-bitmessage_pow.html">bitmessage/pow</a></li><li><a href="module-bitmessage_structs.html">bitmessage/structs</a></li><li><a href="module-bitmessage_user-agent.html">bitmessage/user-agent</a></li><li><a href="module-bitmessage_wif.html">bitmessage/wif</a></li></ul><h3>Classes</h3><ul><li><a href="module-bitmessage_address.Address.html">Address</a></li></ul><h3>Namespaces</h3><ul><li><a href="module-bitmessage_messages.addr.html">addr</a></li><li><a href="module-bitmessage_messages.error.html">error</a></li><li><a href="module-bitmessage_messages.getdata.html">getdata</a></li><li><a href="module-bitmessage_messages.inv.html">inv</a></li><li><a href="module-bitmessage_messages.version.html">version</a></li><li><a href="module-bitmessage_objects.broadcast.html">broadcast</a></li><li><a href="module-bitmessage_objects.getpubkey.html">getpubkey</a></li><li><a href="module-bitmessage_objects.msg.html">msg</a></li><li><a href="module-bitmessage_objects.pubkey.html">pubkey</a></li><li><a href="module-bitmessage_structs.encrypted.html">encrypted</a></li><li><a href="module-bitmessage_structs.inv_vect.html">inv_vect</a></li><li><a href="module-bitmessage_structs.message.html">message</a></li><li><a href="module-bitmessage_structs.net_addr.html">net_addr</a></li><li><a href="module-bitmessage_structs.object.html">object</a></li><li><a href="module-bitmessage_structs.PubkeyBitfield.html">PubkeyBitfield</a></li><li><a href="module-bitmessage_structs.ServicesBitfield.html">ServicesBitfield</a></li><li><a href="module-bitmessage_structs.var_int.html">var_int</a></li><li><a href="module-bitmessage_structs.var_int_list.html">var_int_list</a></li><li><a href="module-bitmessage_structs.var_str.html">var_str</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.0-beta1</a> on Sat Jan 31 2015 14:53:21 GMT+0300 (MSK)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>