From 12f3833cf6b3ab59b675ba77edf6c012e2f8824e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rodr=C3=ADguez?= Date: Thu, 30 Aug 2018 17:58:22 -0500 Subject: Modernize lib/peer.js --- lib/peer.js | 333 +++++++++++++++++++++++++++++------------------------------- 1 file changed, 163 insertions(+), 170 deletions(-) (limited to 'lib') diff --git a/lib/peer.js b/lib/peer.js index cd54403..90dfc30 100644 --- a/lib/peer.js +++ b/lib/peer.js @@ -1,28 +1,28 @@ -var arrayRemove = require('unordered-array-remove') -var debug = require('debug')('webtorrent:peer') -var Wire = require('bittorrent-protocol') +const arrayRemove = require('unordered-array-remove'); +const debug = require('debug')('webtorrent:peer'); +const Wire = require('bittorrent-protocol'); -var WebConn = require('./webconn') +const WebConn = require('./webconn'); -var CONNECT_TIMEOUT_TCP = 5000 -var CONNECT_TIMEOUT_WEBRTC = 25000 -var HANDSHAKE_TIMEOUT = 25000 +const CONNECT_TIMEOUT_TCP = 5000; +const CONNECT_TIMEOUT_WEBRTC = 25000; +const HANDSHAKE_TIMEOUT = 25000; /** * WebRTC peer connections start out connected, because WebRTC peers require an * "introduction" (i.e. WebRTC signaling), and there's no equivalent to an IP address * that lets you refer to a WebRTC endpoint. */ -exports.createWebRTCPeer = function (conn, swarm) { - var peer = new Peer(conn.id, 'webrtc') +exports.createWebRTCPeer = (conn, swarm) => { + const peer = new Peer(conn.id, 'webrtc'); peer.conn = conn peer.swarm = swarm if (peer.conn.connected) { peer.onConnect() } else { - peer.conn.once('connect', function () { peer.onConnect() }) - peer.conn.once('error', function (err) { peer.destroy(err) }) + peer.conn.once('connect', () => { peer.onConnect() }) + peer.conn.once('error', err => { peer.destroy(err) }) peer.startConnectTimeout() } @@ -34,9 +34,9 @@ exports.createWebRTCPeer = function (conn, swarm) { * listening port of the TCP server. Until the remote peer sends a handshake, we don't * know what swarm the connection is intended for. */ -exports.createTCPIncomingPeer = function (conn) { - var addr = conn.remoteAddress + ':' + conn.remotePort - var peer = new Peer(addr, 'tcpIncoming') +exports.createTCPIncomingPeer = conn => { + const addr = `${conn.remoteAddress}:${conn.remotePort}`; + const peer = new Peer(addr, 'tcpIncoming'); peer.conn = conn peer.addr = addr @@ -49,8 +49,8 @@ exports.createTCPIncomingPeer = function (conn) { * Outgoing TCP peers start out with just an IP address. At some point (when there is an * available connection), the client can attempt to connect to the address. */ -exports.createTCPOutgoingPeer = function (addr, swarm) { - var peer = new Peer(addr, 'tcpOutgoing') +exports.createTCPOutgoingPeer = (addr, swarm) => { + const peer = new Peer(addr, 'tcpOutgoing'); peer.addr = addr peer.swarm = swarm @@ -60,8 +60,8 @@ exports.createTCPOutgoingPeer = function (addr, swarm) { /** * Peer that represents a Web Seed (BEP17 / BEP19). */ -exports.createWebSeedPeer = function (url, swarm) { - var peer = new Peer(url, 'webSeed') +exports.createWebSeedPeer = (url, swarm) => { + const peer = new Peer(url, 'webSeed'); peer.swarm = swarm peer.conn = new WebConn(url, swarm) @@ -76,170 +76,163 @@ exports.createWebSeedPeer = function (url, swarm) { * @param {string} id "ip:port" string, peer id (for WebRTC peers), or url (for Web Seeds) * @param {string} type the type of the peer */ -function Peer (id, type) { - var self = this - self.id = id - self.type = type +class Peer { + constructor(id, type) { + this.id = id + this.type = type - debug('new %s Peer %s', type, id) + debug('new %s Peer %s', type, id) - self.addr = null - self.conn = null - self.swarm = null - self.wire = null + this.addr = null + this.conn = null + this.swarm = null + this.wire = null - self.connected = false - self.destroyed = false - self.timeout = null // handshake timeout - self.retries = 0 // outgoing TCP connection retry count + this.connected = false + this.destroyed = false + this.timeout = null // handshake timeout + this.retries = 0 // outgoing TCP connection retry count - self.sentHandshake = false -} - -/** - * Called once the peer is connected (i.e. fired 'connect' event) - * @param {Socket} conn - */ -Peer.prototype.onConnect = function () { - var self = this - if (self.destroyed) return - self.connected = true - - debug('Peer %s connected', self.id) - - clearTimeout(self.connectTimeout) - - var conn = self.conn - conn.once('end', function () { - self.destroy() - }) - conn.once('close', function () { - self.destroy() - }) - conn.once('finish', function () { - self.destroy() - }) - conn.once('error', function (err) { - self.destroy(err) - }) - - var wire = self.wire = new Wire() - wire.type = self.type - wire.once('end', function () { - self.destroy() - }) - wire.once('close', function () { - self.destroy() - }) - wire.once('finish', function () { - self.destroy() - }) - wire.once('error', function (err) { - self.destroy(err) - }) - - wire.once('handshake', function (infoHash, peerId) { - self.onHandshake(infoHash, peerId) - }) - self.startHandshakeTimeout() - - conn.pipe(wire).pipe(conn) - if (self.swarm && !self.sentHandshake) self.handshake() -} - -/** - * Called when handshake is received from remote peer. - * @param {string} infoHash - * @param {string} peerId - */ -Peer.prototype.onHandshake = function (infoHash, peerId) { - var self = this - if (!self.swarm) return // `self.swarm` not set yet, so do nothing - if (self.destroyed) return - - if (self.swarm.destroyed) { - return self.destroy(new Error('swarm already destroyed')) - } - if (infoHash !== self.swarm.infoHash) { - return self.destroy(new Error('unexpected handshake info hash for this swarm')) + this.sentHandshake = false } - if (peerId === self.swarm.peerId) { - return self.destroy(new Error('refusing to connect to ourselves')) - } - - debug('Peer %s got handshake %s', self.id, infoHash) - clearTimeout(self.handshakeTimeout) - - self.retries = 0 - - var addr = self.addr - if (!addr && self.conn.remoteAddress && self.conn.remotePort) { - addr = self.conn.remoteAddress + ':' + self.conn.remotePort + /** + * Called once the peer is connected (i.e. fired 'connect' event) + * @param {Socket} conn + */ + onConnect() { + if (this.destroyed) return + this.connected = true + + debug('Peer %s connected', this.id) + + clearTimeout(this.connectTimeout) + + const conn = this.conn; + conn.once('end', () => { + this.destroy() + }) + conn.once('close', () => { + this.destroy() + }) + conn.once('finish', () => { + this.destroy() + }) + conn.once('error', err => { + this.destroy(err) + }) + + const wire = this.wire = new Wire(); + wire.type = this.type + wire.once('end', () => { + this.destroy() + }) + wire.once('close', () => { + this.destroy() + }) + wire.once('finish', () => { + this.destroy() + }) + wire.once('error', err => { + this.destroy(err) + }) + + wire.once('handshake', (infoHash, peerId) => { + this.onHandshake(infoHash, peerId) + }) + this.startHandshakeTimeout() + + conn.pipe(wire).pipe(conn) + if (this.swarm && !this.sentHandshake) this.handshake() } - self.swarm._onWire(self.wire, addr) - - // swarm could be destroyed in user's 'wire' event handler - if (!self.swarm || self.swarm.destroyed) return - if (!self.sentHandshake) self.handshake() -} - -Peer.prototype.handshake = function () { - var self = this - var opts = { - dht: self.swarm.private ? false : !!self.swarm.client.dht + /** + * Called when handshake is received from remote peer. + * @param {string} infoHash + * @param {string} peerId + */ + onHandshake(infoHash, peerId) { + if (!this.swarm) return // `this.swarm` not set yet, so do nothing + if (this.destroyed) return + + if (this.swarm.destroyed) { + return this.destroy(new Error('swarm already destroyed')) + } + if (infoHash !== this.swarm.infoHash) { + return this.destroy(new Error('unexpected handshake info hash for this swarm')) + } + if (peerId === this.swarm.peerId) { + return this.destroy(new Error('refusing to connect to ourselves')) + } + + debug('Peer %s got handshake %s', this.id, infoHash) + + clearTimeout(this.handshakeTimeout) + + this.retries = 0 + + let addr = this.addr; + if (!addr && this.conn.remoteAddress && this.conn.remotePort) { + addr = `${this.conn.remoteAddress}:${this.conn.remotePort}` + } + this.swarm._onWire(this.wire, addr) + + // swarm could be destroyed in user's 'wire' event handler + if (!this.swarm || this.swarm.destroyed) return + + if (!this.sentHandshake) this.handshake() } - self.wire.handshake(self.swarm.infoHash, self.swarm.client.peerId, opts) - self.sentHandshake = true -} - -Peer.prototype.startConnectTimeout = function () { - var self = this - clearTimeout(self.connectTimeout) - self.connectTimeout = setTimeout(function () { - self.destroy(new Error('connect timeout')) - }, self.type === 'webrtc' ? CONNECT_TIMEOUT_WEBRTC : CONNECT_TIMEOUT_TCP) - if (self.connectTimeout.unref) self.connectTimeout.unref() -} - -Peer.prototype.startHandshakeTimeout = function () { - var self = this - clearTimeout(self.handshakeTimeout) - self.handshakeTimeout = setTimeout(function () { - self.destroy(new Error('handshake timeout')) - }, HANDSHAKE_TIMEOUT) - if (self.handshakeTimeout.unref) self.handshakeTimeout.unref() -} -Peer.prototype.destroy = function (err) { - var self = this - if (self.destroyed) return - self.destroyed = true - self.connected = false - - debug('destroy %s (error: %s)', self.id, err && (err.message || err)) - - clearTimeout(self.connectTimeout) - clearTimeout(self.handshakeTimeout) - - var swarm = self.swarm - var conn = self.conn - var wire = self.wire + handshake() { + const opts = { + dht: this.swarm.private ? false : !!this.swarm.client.dht + }; + this.wire.handshake(this.swarm.infoHash, this.swarm.client.peerId, opts) + this.sentHandshake = true + } - self.swarm = null - self.conn = null - self.wire = null + startConnectTimeout() { + clearTimeout(this.connectTimeout) + this.connectTimeout = setTimeout(() => { + this.destroy(new Error('connect timeout')) + }, this.type === 'webrtc' ? CONNECT_TIMEOUT_WEBRTC : CONNECT_TIMEOUT_TCP) + if (this.connectTimeout.unref) this.connectTimeout.unref() + } - if (swarm && wire) { - arrayRemove(swarm.wires, swarm.wires.indexOf(wire)) + startHandshakeTimeout() { + clearTimeout(this.handshakeTimeout) + this.handshakeTimeout = setTimeout(() => { + this.destroy(new Error('handshake timeout')) + }, HANDSHAKE_TIMEOUT) + if (this.handshakeTimeout.unref) this.handshakeTimeout.unref() } - if (conn) { - conn.on('error', noop) - conn.destroy() + + destroy(err) { + if (this.destroyed) return + this.destroyed = true + this.connected = false + + debug('destroy %s (error: %s)', this.id, err && (err.message || err)) + + clearTimeout(this.connectTimeout) + clearTimeout(this.handshakeTimeout) + + const swarm = this.swarm; + const conn = this.conn; + const wire = this.wire; + + this.swarm = null + this.conn = null + this.wire = null + + if (swarm && wire) { + arrayRemove(swarm.wires, swarm.wires.indexOf(wire)) + } + if (conn) { + conn.on('error', () => {}) + conn.destroy() + } + if (wire) wire.destroy() + if (swarm) swarm.removePeer(this.id) } - if (wire) wire.destroy() - if (swarm) swarm.removePeer(self.id) } - -function noop () {} -- cgit v1.2.3