diff --git a/lib/transport/index.js b/lib/transport/index.js index 7d25662..6e49efa 100644 --- a/lib/transport/index.js +++ b/lib/transport/index.js @@ -2,8 +2,5 @@ * @namespace Transport */ module.exports = { - explorers: require('./explorers'), - Messages: require('./messages'), - Peer: require('./peer'), - Pool: require('./pool') + explorers: require('./explorers') }; diff --git a/lib/transport/messages.js b/lib/transport/messages.js deleted file mode 100644 index ffe82c7..0000000 --- a/lib/transport/messages.js +++ /dev/null @@ -1,613 +0,0 @@ -'use strict'; -/** - * @namespace Transport.Message - */ -/* jshint curly: false */ - -var Buffers = require('buffers'); -var Put = require('bufferput'); -var util = require('util'); - -var BlockHeaderModel = require('../blockheader'); -var BlockModel = require('../block'); -var BufferReader = require('../encoding/bufferreader'); -var BufferUtil = require('../util/buffer'); -var Hash = require('../crypto/hash'); -var Random = require('../crypto/random'); -var TransactionModel = require('../transaction'); - -var CONNECTION_NONCE = Random.getPseudoRandomBuffer(8); -var PROTOCOL_VERSION = 70000; - -/** - * Static helper for consuming a data buffer until the next message. - * - * @name Transport.Message#parseMessage - * @param{Network} network - the network object - * @param{Buffer} dataBuffer - the buffer to read from - * @returns{Message|undefined} A message or undefined if there is nothing to read. - */ -var parseMessage = function(network, dataBuffer) { - if (dataBuffer.length < 20) return; - - // Search the next magic number - if (!discardUntilNextMessage(network, dataBuffer)) return; - - var PAYLOAD_START = 16; - var payloadLen = (dataBuffer.get(PAYLOAD_START)) + - (dataBuffer.get(PAYLOAD_START + 1) << 8) + - (dataBuffer.get(PAYLOAD_START + 2) << 16) + - (dataBuffer.get(PAYLOAD_START + 3) << 24); - - var messageLength = 24 + payloadLen; - if (dataBuffer.length < messageLength) return; - - var command = dataBuffer.slice(4, 16).toString('ascii').replace(/\0+$/, ''); - var payload = dataBuffer.slice(24, messageLength); - var checksum = dataBuffer.slice(20, 24); - - var checksumConfirm = Hash.sha256sha256(payload).slice(0, 4); - if (!BufferUtil.equals(checksumConfirm, checksum)) { - dataBuffer.skip(messageLength); - return; - } - - dataBuffer.skip(messageLength); - return Message.buildMessage(command, payload); -}; - -module.exports.parseMessage = parseMessage; - -/** - * @desc Internal function that discards data until founds the next message. - * @name Transport.Message#discardUntilNextMessage - */ -function discardUntilNextMessage(network, dataBuffer) { - var magicNumber = network.networkMagic; - - var i = 0; - for (;;) { - // check if it's the beginning of a new message - var packageNumber = dataBuffer.slice(0, 4); - if (BufferUtil.equals(packageNumber, magicNumber)) { - dataBuffer.skip(i); - return true; - } - - // did we reach the end of the buffer? - if (i > (dataBuffer.length - 4)) { - dataBuffer.skip(i); - return false; - } - - i++; // continue scanning - } -} - -/** - * Abstract Message that knows how to parse and serialize itself. - * Concret subclases should implement {fromBuffer} and {getPayload} methods. - * @name Transport.Message - */ -function Message() {} - -/** - * @value - * @name Transport.Message.COMMANDS - */ -Message.COMMANDS = {}; - -/** - * Look up a message type by command name and instantiate the correct Message - * @name Transport.Message#buildMessage - */ -Message.buildMessage = function(command, payload) { - try { - var CommandClass = Message.COMMANDS[command]; - return new CommandClass().fromBuffer(payload); - } catch (err) { - console.log('Error while parsing message', err); - } -}; - -/** - * Parse instance state from buffer. - * - * @param{Buffer} payload - the buffer to read from - * @returns{Message} The same message instance - */ -Message.prototype.fromBuffer = function(payload) { - /* jshint unused: false */ - return this; -}; - -/** - * Serialize the payload into a buffer. - * - * @returns{Buffer} the serialized payload - */ -Message.prototype.getPayload = function() { - return BufferUtil.EMPTY_BUFFER; -}; - -/** - * Serialize the message into a buffer. - * - * @returns{Buffer} the serialized message - */ -Message.prototype.serialize = function(network) { - var magic = network.networkMagic; - var commandBuf = new Buffer(this.command, 'ascii'); - if (commandBuf.length > 12) throw 'Command name too long'; - - var payload = this.getPayload(); - var checksum = Hash.sha256sha256(payload).slice(0, 4); - - // -- HEADER -- - var message = new Put(); - message.put(magic); - message.put(commandBuf); - message.pad(12 - commandBuf.length); // zero-padded - message.word32le(payload.length); - message.put(checksum); - - // -- BODY -- - message.put(payload); - - return message.buffer(); -}; - -module.exports.Message = Message; - -/** - * Version Message - * - * @name Transport.Message.Version - * @param{string} subversion - version of the client - * @param{Buffer} nonce - a random 8 bytes buffer - */ -function Version(subversion, nonce) { - this.command = 'version'; - this.version = PROTOCOL_VERSION; - this.subversion = subversion || '/BitcoinX:0.1/'; - this.nonce = nonce || CONNECTION_NONCE; -} -util.inherits(Version, Message); - -Version.prototype.fromBuffer = function(payload) { - var parser = new BufferReader(payload); - this.version = parser.readUInt32LE(); - this.services = parser.readUInt64LEBN(); - this.timestamp = parser.readUInt64LEBN(); - this.addr_me = parser.read(26); - this.addr_you = parser.read(26); - this.nonce = parser.read(8); - this.subversion = parser.readVarintBuf().toString(); - this.start_height = parser.readUInt32LE(); - - return this; -}; - -Version.prototype.getPayload = function() { - var put = new Put(); - put.word32le(this.version); // version - put.word64le(1); // services - put.word64le(Math.round(new Date().getTime() / 1000)); // timestamp - put.pad(26); // addr_me - put.pad(26); // addr_you - put.put(this.nonce); - put.varint(this.subversion.length); - put.put(new Buffer(this.subversion, 'ascii')); - put.word32le(0); - - return put.buffer(); -}; - -module.exports.Version = Message.COMMANDS.version = Version; - -/** - * Inv Message - * - * @name Transport.Message.Inventory - * @param{Array} inventory - reported elements - */ -function Inventory(inventory) { - this.command = 'inv'; - this.inventory = inventory || []; -} -util.inherits(Inventory, Message); - -Inventory.prototype.fromBuffer = function(payload) { - var parser = new BufferReader(payload); - var count = parser.readVarintNum(); - for (var i = 0; i < count; i++) { - this.inventory.push({ - type: parser.readUInt32LE(), - hash: parser.read(32) - }); - } - - return this; -}; - -Inventory.prototype.getPayload = function() { - var put = new Put(); - - put.varint(this.inventory.length); - this.inventory.forEach(function(value) { - put.word32le(value.type); - put.put(value.hash); - }); - - return put.buffer(); -}; - -module.exports.Inventory = Message.COMMANDS.inv = Inventory; - -/** - * Getdata Message - * - * @name Transport.Message.GetData - * @param{Array} inventory - requested elements - */ -function GetData(inventory) { - this.command = 'getdata'; - this.inventory = inventory || []; -} - -util.inherits(GetData, Inventory); -module.exports.GetData = GetData; - -/** - * Ping Message - * - * @name Transport.Message.Ping - * @param{Buffer} nonce - a random 8 bytes buffer - */ -function Ping(nonce) { - this.command = 'ping'; - this.nonce = nonce || CONNECTION_NONCE; -} -util.inherits(Ping, Message); - -Ping.prototype.fromBuffer = function(payload) { - this.nonce = new BufferReader(payload).read(8); - return this; -}; - -Ping.prototype.getPayload = function() { - return this.nonce; -}; - -module.exports.Ping = Message.COMMANDS.ping = Ping; - -/** - * Pong Message - * - * @name Transport.Message.Pong - * @param{Buffer} nonce - a random 8 bytes buffer - */ -function Pong(nonce) { - this.command = 'pong'; - this.nonce = nonce || CONNECTION_NONCE; -} - -util.inherits(Pong, Ping); -module.exports.Pong = Message.COMMANDS.pong = Pong; - -/** - * Addr Message - * - * @name Transport.Message.Addressess - * @param{Array} addresses - array of know addresses - */ -function Addresses(addresses) { - this.command = 'addr'; - this.addresses = addresses || []; -} -util.inherits(Addresses, Message); - -Addresses.prototype.fromBuffer = function(payload) { - var parser = new BufferReader(payload); - var addrCount = Math.min(parser.readVarintNum(), 1000); - - this.addresses = []; - for (var i = 0; i < addrCount; i++) { - // TODO: Time actually depends on the version of the other peer (>=31402) - - var time = parser.readUInt32LE(); - var services = parser.readUInt64LEBN(); - - // parse the ipv6 to a string - var ipv6 = []; - for (var a = 0; a < 6; a++) { - ipv6.push(parser.read(2).toString('hex')); - } - 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('.'); - - var port = parser.readUInt16BE(); - - this.addresses.push({ - time: time, - services: services, - ip: { v6: ipv6, v4: ipv4 }, - port: port - }); - } - - return this; -}; - -Addresses.prototype.getPayload = function() { - var put = new Put(); - put.varint(this.addresses.length); - - for (var i = 0; i < this.addresses.length; i++) { - put.word32le(this.addresses[i].time); - put.word64le(this.addresses[i].services); - put.put(this.addresses[i].ip); - put.word16be(this.addresses[i].port); - } - - return put.buffer(); -}; - -module.exports.Addresses = Message.COMMANDS.addr = Addresses; - -/** - * GetAddr Message - * - * @name Transport.Message.GetAddresses - */ -function GetAddresses() { - this.command = 'getaddr'; -} - -util.inherits(GetAddresses, Message); -module.exports.GetAddresses = Message.COMMANDS.getaddr = GetAddresses; - -/** - * Verack Message - * - * @name Transport.Message.VerAck - */ -function VerAck() { - this.command = 'verack'; -} - -util.inherits(VerAck, Message); -module.exports.VerAck = Message.COMMANDS.verack = VerAck; - -/** - * Reject Message - * - * @name Transport.Message.Reject - */ -function Reject() { - this.command = 'reject'; -} -util.inherits(Reject, Message); - -// TODO: Parse REJECT message - -module.exports.Reject = Message.COMMANDS.reject = Reject; - -/** - * Alert Message - * - * @name Transport.Message.Alert - */ -function Alert(payload, signature) { - this.command = 'alert'; - this.payload = payload || new Buffer(32); - this.signature = signature || new Buffer(32); -} -util.inherits(Alert, Message); - -Alert.prototype.fromBuffer = function(payload) { - var parser = new BufferReader(payload); - this.payload = parser.readVarintBuf(); // TODO: Use current format - this.signature = parser.readVarintBuf(); - return this; -}; - -Alert.prototype.getPayload = function() { - var put = new Put(); - put.varint(this.payload.length); - put.put(this.payload); - - put.varint(this.signature.length); - put.put(this.signature); - - return put.buffer(); -}; - -module.exports.Alert = Message.COMMANDS.alert = Alert; - -/** - * Headers Message - * - * @name Transport.Message.Headers - * @param{Array} blockheaders - array of block headers - */ -function Headers(blockheaders) { - this.command = 'headers'; - this.headers = blockheaders || []; -} -util.inherits(Headers, Message); - -Headers.prototype.fromBuffer = function(payload) { - var parser = new BufferReader(payload); - var count = parser.readVarintNum(); - - this.headers = []; - for (var i = 0; i < count; i++) { - var header = BlockHeaderModel._fromBufferReader(parser); - this.headers.push(header); - } - - return this; -}; - -Headers.prototype.getPayload = function() { - var put = new Put(); - put.varint(this.headers.length); - - for (var i = 0; i < this.headers.length; i++) { - var buffer = this.headers[i].toBuffer(); - put.put(buffer); - } - - return put.buffer(); -}; - -module.exports.Headers = Message.COMMANDS.headers = Headers; - -/** - * Block Message - * - * @name Transport.Message.Block - * @param{Block} block - */ -function Block(block) { - this.command = 'block'; - this.block = block; -} -util.inherits(Block, Message); - -Block.prototype.fromBuffer = function(payload) { - this.block = BlockModel(payload); - return this; -}; - -Block.prototype.getPayload = function() { - return this.block.toBuffer(); -}; - -module.exports.Block = Message.COMMANDS.block = Block; - -/** - * Tx Message - * - * @name Transport.Message.Transaction - * @param{Transaction} transaction - */ -function Transaction(transaction) { - this.command = 'tx'; - this.transaction = transaction; -} -util.inherits(Transaction, Message); - -Transaction.prototype.fromBuffer = function(payload) { - this.transaction = TransactionModel(payload); - return this; -}; - -Transaction.prototype.getPayload = function() { - return this.transaction.toBuffer(); -}; - -module.exports.Transaction = Message.COMMANDS.tx = Transaction; - -/** - * Getblocks Message - * - * @name Transport.Message.GetBlocks - * @param{Array} starts - array of buffers with the starting block hashes - * @param{Buffer} [stop] - hash of the last block - */ -function GetBlocks(starts, stop) { - this.command = 'getblocks'; - this.version = PROTOCOL_VERSION; - this.starts = starts || []; - this.stop = stop || BufferUtil.NULL_HASH; -} -util.inherits(GetBlocks, Message); - -GetBlocks.prototype.fromBuffer = function(payload) { - var parser = new BufferReader(payload); - this.version = parser.readUInt32LE(); - - var startCount = Math.min(parser.readVarintNum(), 500); - this.starts = []; - for (var i = 0; i < startCount; i++) { - this.starts.push(parser.read(32)); - } - this.stop = parser.read(32); - - return this; -}; - -GetBlocks.prototype.getPayload = function() { - var put = new Put(); - put.word32le(this.version); - put.varint(this.starts.length); - - for (var i = 0; i < this.starts.length; i++) { - if (this.starts[i].length !== 32) { - throw new Error('Invalid hash length'); - } - put.put(this.starts[i]); - } - - if (this.stop.length !== 32) { - throw new Error('Invalid hash length'); - } - put.put(this.stop); - - return put.buffer(); -}; - -module.exports.GetBlocks = Message.COMMANDS.getblocks = GetBlocks; - -/** - * Getheaders Message - * - * @name Transport.Message.GetHeaders - * @param{Array} starts - array of buffers with the starting block hashes - * @param{Buffer} [stop] - hash of the last block - */ -function GetHeaders(starts, stop) { - this.command = 'getheaders'; - this.version = PROTOCOL_VERSION; - this.starts = starts || []; - this.stop = stop || BufferUtil.NULL_HASH; -} - -util.inherits(GetHeaders, GetBlocks); -module.exports.GetHeaders = Message.COMMANDS.getheaders = GetHeaders; - -/** - * GetMempool Message - * - * @name Transport.Message.GetMempool - */ -function GetMempool() { - this.command = 'mempool'; -} - -util.inherits(GetMempool, Message); -module.exports.GetMempool = Message.COMMANDS.mempool = GetMempool; - -// TODO: Remove this PATCH (yemel) -Buffers.prototype.skip = function (i) { - if (i === 0) return; - - if (i === this.length) { - this.buffers = []; - this.length = 0; - return; - } - - var pos = this.pos(i); - this.buffers = this.buffers.slice(pos.buf); - this.buffers[0] = new Buffer(this.buffers[0].slice(pos.offset)); - this.length -= i; -}; diff --git a/lib/transport/peer.js b/lib/transport/peer.js deleted file mode 100644 index 1c10f1b..0000000 --- a/lib/transport/peer.js +++ /dev/null @@ -1,194 +0,0 @@ -'use strict'; - -var Buffers = require('buffers'); -var EventEmitter = require('events').EventEmitter; -var Net = require('net'); -var Socks5Client = require('socks5-client'); -var util = require('util'); - -var Networks = require('../networks'); -var Messages = require('./messages'); - -var MAX_RECEIVE_BUFFER = 10000000; - -/** - * A Peer instance represents a remote bitcoin node and allows to communicate - * with it using the standar messages of the bitcoin p2p protocol. - * - * @example - * ```javascript - * - * var peer = new Peer('127.0.0.1').setProxy('127.0.0.1', 9050); - * peer.on('tx', function(tx) { - * console.log('New transaction: ', tx.id); - * }); - * peer.connect(); - * ``` - * - * @param {String} host - IP address of the remote host - * @param {Number} [port] - Port number of the remote host - * @param {Network} [network] - The context for this communication - * @returns {Peer} A new instance of Peer. - * @constructor - */ -function Peer(host, port, network) { - if (!(this instanceof Peer)) { - return new Peer(host, port, network); - } - - // overloading stuff - if (port instanceof Object && !network) { - network = port; - port = undefined; - } - - this.host = host; - this.status = Peer.STATUS.DISCONNECTED; - this.network = network || Networks.livenet; - this.port = port || this.network.port; - - this.dataBuffer = new Buffers(); - - this.version = 0; - this.bestHeight = 0; - this.subversion = null; - - // set message handlers - var self = this; - this.on('verack', function() { - self.status = Peer.STATUS.READY; - self.emit('ready'); - }); - - this.on('version', function(message) { - self.version = message.version; - self.subversion = message.subversion; - self.bestHeight = message.start_height - }); - - this.on('ping', function(message) { - self._sendPong(message.nonce); - }); - -} -util.inherits(Peer, EventEmitter); - -Peer.STATUS = { - DISCONNECTED: 'disconnected', - CONNECTING: 'connecting', - CONNECTED: 'connected', - READY: 'ready' -}; - -/** - * Set a socks5 proxy for the connection. Enables the use of the TOR network. - * - * @param {String} host - IP address of the proxy - * @param {Number} port - Port number of the proxy - * @returns {Peer} The same Peer instance. - */ -Peer.prototype.setProxy = function(host, port) { - if (this.status != Peer.STATUS.DISCONNECTED) { - throw Error('Invalid State'); - } - - this.proxy = { - host: host, - port: port - }; - return this; -}; - -/** - * Init the connection with the remote peer. - * - * @returns {Socket} The same peer instance. - */ -Peer.prototype.connect = function() { - this.socket = this._getSocket(); - this.status = Peer.STATUS.CONNECTING; - - var self = this; - this.socket.on('connect', function(ev) { - self.status = Peer.STATUS.CONNECTED; - self.emit('connect'); - self._sendVersion(); - }); - - this.socket.on('error', self.disconnect.bind(this)); - this.socket.on('end', self.disconnect.bind(this)); - - this.socket.on('data', function(data) { - self.dataBuffer.push(data); - - if (self.dataBuffer.length > MAX_RECEIVE_BUFFER) return self.disconnect(); - self._readMessage(); - }); - - this.socket.connect(this.port, this.host); - return this; -}; - -/** - * Disconnects the remote connection. - * - * @returns {Socket} The same peer instance. - */ -Peer.prototype.disconnect = function() { - this.status = Peer.STATUS.DISCONNECTED; - this.socket.destroy(); - this.emit('disconnect'); - return this; -}; - -/** - * Send a Message to the remote peer. - * - * @param {Message} message - A message instance - */ -Peer.prototype.sendMessage = function(message) { - this.socket.write(message.serialize(this.network)); -}; - -/** - * Internal function that sends VERSION message to the remote peer. - */ -Peer.prototype._sendVersion = function() { - var message = new Messages.Version(); - this.sendMessage(message); -}; - -/** - * Send a PONG message to the remote peer. - */ -Peer.prototype._sendPong = function(nonce) { - var message = new Messages.Pong(nonce); - this.sendMessage(message); -}; - -/** - * Internal function that tries to read a message from the data buffer - */ -Peer.prototype._readMessage = function() { - var message = Messages.parseMessage(this.network, this.dataBuffer); - - if (message) { - this.emit(message.command, message); - this._readMessage(); - } -}; - -/** - * Internal function that creates a socket using a proxy if neccesary. - * - * @returns {Socket} A Socket instance not yet connected. - */ -Peer.prototype._getSocket = function() { - if (this.proxy) { - return new Socks5Client(this.proxy.host, this.proxy.port); - } - - return new Net.Socket(); -}; - -module.exports = Peer; diff --git a/lib/transport/pool.js b/lib/transport/pool.js deleted file mode 100644 index ec2b64c..0000000 --- a/lib/transport/pool.js +++ /dev/null @@ -1,275 +0,0 @@ -'use strict'; - -var dns = require('dns'); -var EventEmitter = require('events').EventEmitter; -var Networks = require('../networks'); -var sha256 = require('../crypto/hash').sha256; -var Peer = require('./peer'); -var util = require('util'); - -function now() { - return Math.floor(new Date().getTime() / 1000); -} - -/** - * A pool is a collection of Peers. A pool will discover peers from DNS seeds, and - * collect information about new peers in the network. When a peer disconnects the pool - * will connect to others that are available to maintain a max number of - * ongoing peer connections. Peer events are relayed to the pool. - * - * @example - * ```javascript - * - * var pool = new Pool(Networks.livenet); - * pool.on('peerinv', function(peer, message) { - * // do something with the inventory announcement - * }); - * pool.connect(); - * ``` - * - * @param {Network|String} network - The network to connect - * @returns {Pool} - * @constructor - */ -function Pool(network) { - - var self = this; - - this.network = Networks.get(network) || Networks.defaultNetwork; - this.keepalive = false; - this._connectedPeers = {}; - this._addrs = []; - - this.on('peeraddr', function peerAddrEvent(peer, message) { - var addrs = message.addresses; - var length = addrs.length; - for (var i = 0; i < length; i++) { - var addr = addrs[i]; - // In case of an invalid time, assume "5 days ago" - if (addr.time <= 100000000 || addr.time > (now() + 10 * 60)) { - addr.time = now() - 5 * 24 * 60 * 60; - } - this._addAddr(addr); - } - }); - - this.on('seed', function seedEvent(ips) { - ips.forEach(function(ip) { - self._addAddr({ - ip: { - v4: ip - } - }); - }); - if (self.keepalive) { - self._fillConnections(); - } - }); - - this.on('peerdisconnect', function peerDisconnectEvent(peer, addr) { - self._deprioritizeAddr(addr); - self._removeConnectedPeer(addr); - if (self.keepalive) { - self._fillConnections(); - } - }); - - return this; - -} - -util.inherits(Pool, EventEmitter); - -Pool.MaxConnectedPeers = 8; -Pool.RetrySeconds = 30; -Pool.PeerEvents = ['version', 'inv', 'getdata', 'ping', 'ping', 'addr', - 'getaddr', 'verack', 'reject', 'alert', 'headers', 'block', - 'tx', 'getblocks', 'getheaders' -]; - - -/** - * Will initiatiate connection to peers, if available peers have been added to - * the pool, it will connect to those, otherwise will use DNS seeds to find - * peers to connect. When a peer disconnects it will add another. - */ -Pool.prototype.connect = function connect() { - this.keepalive = true; - var self = this; - if (self._addrs.length === 0) { - self._addAddrsFromSeeds(); - } else { - self._fillConnections(); - } - return this; -}; - - -/** - * Will disconnect all peers that are connected. - */ -Pool.prototype.disconnect = function disconnect() { - this.keepalive = false; - for (var i in this._connectedPeers) { - this._connectedPeers[i].disconnect(); - } - return this; -}; - -/** - * @returns {Number} The number of peers currently connected. - */ -Pool.prototype.numberConnected = function numberConnected() { - return Object.keys(this._connectedPeers).length; -}; - -/** - * Will fill the conneted peers to the maximum amount. - */ -Pool.prototype._fillConnections = function _fillConnections() { - var length = this._addrs.length; - for (var i = 0; i < length; i++) { - if (this.numberConnected() >= Pool.MaxConnectedPeers) { - break; - } - var addr = this._addrs[i]; - if (!addr.retryTime || now() > addr.retryTime) { - this._connectPeer(addr); - } - } - return this; -}; - -/** - * Will remove a peer from the list of connected peers. - * @param {Object} addr - An addr from the list of addrs - */ -Pool.prototype._removeConnectedPeer = function _removeConnectedPeer(addr) { - if (this._connectedPeers[addr.hash].status !== Peer.STATUS.DISCONNECTED) { - this._connectedPeers[addr.hash].disconnect(); - } else { - delete this._connectedPeers[addr.hash]; - } - return this; -}; - -/** - * Will connect a peer and add to the list of connected peers. - * @param {Object} addr - An addr from the list of addrs - */ -Pool.prototype._connectPeer = function _connectPeer(addr) { - var self = this; - - function addConnectedPeer(addr) { - var port = addr.port || self.network.port; - var ip = addr.ip.v4 || addr.ip.v6; - var peer = new Peer(ip, port, self.network); - peer.on('disconnect', function peerDisconnect() { - self.emit('peerdisconnect', peer, addr); - }); - peer.on('ready', function peerReady() { - self.emit('peerready', peer, addr); - }); - Pool.PeerEvents.forEach(function addPeerEvents(event) { - peer.on(event, function peerEvent(message) { - self.emit('peer' + event, peer, message); - }); - }); - peer.connect(); - self._connectedPeers[addr.hash] = peer; - } - - if (!this._connectedPeers[addr.hash]) { - addConnectedPeer(addr); - } - - return this; -}; - -/** - * Will deprioritize an addr in the list of addrs by moving it to the end - * of the array, and setting a retryTime - * @param {Object} addr - An addr from the list of addrs - */ -Pool.prototype._deprioritizeAddr = function _deprioritizeAddr(addr) { - for (var i = 0; i < this._addrs.length; i++) { - if (this._addrs[i].hash === addr.hash) { - var middle = this._addrs[i]; - middle.retryTime = now() + Pool.RetrySeconds; - var beginning = this._addrs.splice(0, i); - var end = this._addrs.splice(i + 1, this._addrs.length); - var combined = beginning.concat(end); - this._addrs = combined.concat([middle]); - } - } - return this; -}; - -/** - * Will add an addr to the beginning of the addrs array - * @param {Object} - */ -Pool.prototype._addAddr = function _addAddr(addr) { - - // make a unique key - addr.hash = sha256(new Buffer(addr.ip.v6 + addr.ip.v4 + addr.port)).toString('hex'); - - var length = this._addrs.length; - var exists = false; - for (var i = 0; i < length; i++) { - if (this._addrs[i].hash === addr.hash) { - exists = true; - } - } - if (!exists) { - this._addrs.unshift(addr); - } - return this; -}; - -/** - * Will add addrs to the list of addrs from a DNS seed - * @param {String} seed - A domain name to resolve known peers - * @param {Function} done - */ -Pool.prototype._addAddrsFromSeed = function _addAddrsFromSeed(seed) { - var self = this; - dns.resolve(seed, function(err, ips) { - if (err) { - self.emit('seederror', err); - return; - } - if (!ips || !ips.length) { - self.emit('seederror', new Error('No IPs found from seed lookup.')); - return; - } - // announce to pool - self.emit('seed', ips); - }); - return this; -}; - -/** - * Will add addrs to the list of addrs from network DNS seeds - * @param {Function} done - */ -Pool.prototype._addAddrsFromSeeds = function _addAddrsFromSeeds() { - var self = this; - var seeds = this.network.dnsSeeds; - seeds.forEach(function(seed) { - self._addAddrsFromSeed(seed); - }); - return this; -}; - -/** - * @returns {String} A string formatted for the console - */ -Pool.prototype.inspect = function inspect() { - return ''; -}; - -module.exports = Pool;