diff --git a/lib/messages/commands/verack.js b/lib/messages/commands/verack.js index 1653612..5def3e2 100644 --- a/lib/messages/commands/verack.js +++ b/lib/messages/commands/verack.js @@ -8,6 +8,10 @@ var BufferUtil = bitcore.util.buffer; var magicNumber = bitcore.Networks.defaultNetwork.networkMagic.readUInt32LE(0); function VerackMessage(options) { + if(!options) { + options = {}; + } + Message.call(this, options); this.magicNumber = magicNumber; this.command = 'verack'; diff --git a/lib/peer.js b/lib/peer.js index ac05bb2..2757543 100644 --- a/lib/peer.js +++ b/lib/peer.js @@ -38,10 +38,17 @@ function Peer(options) { return new Peer(options); } - this.host = options.host || 'localhost'; - this.status = Peer.STATUS.DISCONNECTED; - this.port = options.port; - + if(options.socket) { + this.socket = options.socket; + this.host = this.socket.remoteAddress; + this.port = this.socket.remotePort; + this.status = Peer.STATUS.CONNECTED; + this._addSocketEventHandlers(); + } else { + this.host = options.host || 'localhost'; + this.status = Peer.STATUS.DISCONNECTED; + this.port = options.port; + } this.network = Networks.get(options.network) || Networks.defaultNetwork; if (!this.port) { @@ -61,6 +68,8 @@ function Peer(options) { this.subversion = null; this.relay = options.relay === false ? false : true; + this.versionSent = false; + // set message handlers var self = this; this.on('verack', function() { @@ -72,6 +81,13 @@ function Peer(options) { self.version = message.version; self.subversion = message.subversion; self.bestHeight = message.startHeight; + + var verackResponse = self.messages.build('verack'); + self.sendMessage(verackResponse); + + if(!self.versionSent) { + self._sendVersion(); + } }); this.on('ping', function(message) { @@ -122,6 +138,14 @@ Peer.prototype.connect = function() { self._sendVersion(); }); + this._addSocketEventHandlers(); + this.socket.connect(this.port, this.host); + return this; +}; + +Peer.prototype._addSocketEventHandlers = function() { + var self = this; + this.socket.on('error', self._onError.bind(this)); this.socket.on('end', self.disconnect.bind(this)); @@ -134,13 +158,11 @@ Peer.prototype.connect = function() { } self._readMessage(); }); - - this.socket.connect(this.port, this.host); - return this; }; Peer.prototype._onError = function(e) { this.emit('error', e); + this.disconnect(); }; /** @@ -172,6 +194,7 @@ Peer.prototype._sendVersion = function() { var message = this.messages.build('version', { relay: this.relay }); + this.versionSent = true; this.sendMessage(message); }; diff --git a/lib/pool.js b/lib/pool.js index 7e613e6..70481bf 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -7,6 +7,7 @@ var sha256 = bitcore.crypto.Hash.sha256; var Peer = require('./peer'); var Networks = bitcore.Networks; var util = require('util'); +var net = require('net'); function now() { return Math.floor(new Date().getTime() / 1000); @@ -126,6 +127,8 @@ Pool.prototype.connect = function connect() { } else { self._fillConnections(); } + + this.listen(); return this; }; @@ -185,40 +188,61 @@ Pool.prototype._removeConnectedPeer = function _removeConnectedPeer(addr) { Pool.prototype._connectPeer = function _connectPeer(addr) { var self = this; - function addConnectedPeer(addr) { + if (!this._connectedPeers[addr.hash]) { var port = addr.port || self.network.port; var ip = addr.ip.v4 || addr.ip.v6; var peer = new Peer({ - ip: ip, + host: ip, port: port, messages: self.messages, relay: self.relay }); - peer.on('disconnect', function peerDisconnect() { - self.emit('peerdisconnect', peer, addr); - }); + peer.on('connect', function peerConnect() { self.emit('peerconnect', 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); - }); - }); + + self._addPeerEventHandlers(peer, addr); peer.connect(); self._connectedPeers[addr.hash] = peer; } + return this; +}; + +Pool.prototype._addConnectedPeer = function _addConnectedPeer(socket, addr) { + var self = this; + if (!this._connectedPeers[addr.hash]) { - addConnectedPeer(addr); + var peer = new Peer({ + socket: socket, + messages: self.messages + }); + + self._addPeerEventHandlers(peer, addr); + self._connectedPeers[addr.hash] = peer; + self.emit('peerconnect', peer, addr); } return this; }; +Pool.prototype._addPeerEventHandlers = function(peer, addr) { + var self = this; + + 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); + }); + }); +}; + /** * Will deprioritize an addr in the list of addrs by moving it to the end * of the array, and setting a retryTime @@ -257,7 +281,7 @@ Pool.prototype._addAddr = function _addAddr(addr) { if (!exists) { this._addrs.unshift(addr); } - return this; + return addr; }; /** @@ -313,4 +337,24 @@ Pool.prototype.sendMessage = function(message) { } }; +Pool.prototype.listen = function() { + var self = this; + + // Create server + this.server = net.createServer(function(socket) { + var addr = { + ip: {} + }; + if(net.isIPv6(socket.remoteAddress)) { + addr.ip.v6 = socket.remoteAddress; + } else { + addr.ip.v4 = socket.remoteAddress; + } + + addr = self._addAddr(addr); + self._addConnectedPeer(socket, addr); + }); + this.server.listen(this.network.port); +}; + module.exports = Pool;