Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/webtorrent/webtorrent.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKayleePop <34007889+KayleePop@users.noreply.github.com>2018-08-26 22:13:13 +0300
committerKayleePop <34007889+KayleePop@users.noreply.github.com>2018-08-26 22:13:13 +0300
commit27327915e92ee6058be6441a01cd937aa8c1bcd4 (patch)
tree4fdf029c9ee4abde921ce590234c2833be6a6367 /lib
parentb97e79825659dbc6c5eb2242d307b2850cdcf139 (diff)
remove `self = this` in torrent.js
Diffstat (limited to 'lib')
-rw-r--r--lib/torrent.js690
1 files changed, 328 insertions, 362 deletions
diff --git a/lib/torrent.js b/lib/torrent.js
index a32326a..5f86228 100644
--- a/lib/torrent.js
+++ b/lib/torrent.js
@@ -179,10 +179,9 @@ class Torrent extends EventEmitter {
}
get _numConns () {
- const self = this
let numConns = 0
- for (const id in self._peers) {
- if (self._peers[id].connected) numConns += 1
+ for (const id in this._peers) {
+ if (this._peers[id].connected) numConns += 1
}
return numConns
}
@@ -194,61 +193,59 @@ class Torrent extends EventEmitter {
}
_onTorrentId (torrentId) {
- const self = this
- if (self.destroyed) return
+ if (this.destroyed) return
let parsedTorrent
try { parsedTorrent = parseTorrent(torrentId) } catch (err) {}
if (parsedTorrent) {
// Attempt to set infoHash property synchronously
- self.infoHash = parsedTorrent.infoHash
- self._debugId = parsedTorrent.infoHash.toString('hex').substring(0, 7)
+ this.infoHash = parsedTorrent.infoHash
+ this._debugId = parsedTorrent.infoHash.toString('hex').substring(0, 7)
process.nextTick(() => {
- if (self.destroyed) return
- self._onParsedTorrent(parsedTorrent)
+ if (this.destroyed) return
+ this._onParsedTorrent(parsedTorrent)
})
} else {
// If torrentId failed to parse, it could be in a form that requires an async
// operation, i.e. http/https link, filesystem path, or Blob.
parseTorrent.remote(torrentId, (err, parsedTorrent) => {
- if (self.destroyed) return
- if (err) return self._destroy(err)
- self._onParsedTorrent(parsedTorrent)
+ if (this.destroyed) return
+ if (err) return this._destroy(err)
+ this._onParsedTorrent(parsedTorrent)
})
}
}
_onParsedTorrent (parsedTorrent) {
- const self = this
- if (self.destroyed) return
+ if (this.destroyed) return
- self._processParsedTorrent(parsedTorrent)
+ this._processParsedTorrent(parsedTorrent)
- if (!self.infoHash) {
- return self._destroy(new Error('Malformed torrent data: No info hash'))
+ if (!this.infoHash) {
+ return this._destroy(new Error('Malformed torrent data: No info hash'))
}
- if (!self.path) self.path = path.join(TMP, self.infoHash)
+ if (!this.path) this.path = path.join(TMP, this.infoHash)
- self._rechokeIntervalId = setInterval(() => {
- self._rechoke()
+ this._rechokeIntervalId = setInterval(() => {
+ this._rechoke()
}, RECHOKE_INTERVAL)
- if (self._rechokeIntervalId.unref) self._rechokeIntervalId.unref()
+ if (this._rechokeIntervalId.unref) this._rechokeIntervalId.unref()
// Private 'infoHash' event allows client.add to check for duplicate torrents and
// destroy them before the normal 'infoHash' event is emitted. Prevents user
// applications from needing to deal with duplicate 'infoHash' events.
- self.emit('_infoHash', self.infoHash)
- if (self.destroyed) return
+ this.emit('_infoHash', this.infoHash)
+ if (this.destroyed) return
- self.emit('infoHash', self.infoHash)
- if (self.destroyed) return // user might destroy torrent in event handler
+ this.emit('infoHash', this.infoHash)
+ if (this.destroyed) return // user might destroy torrent in event handler
- if (self.client.listening) {
- self._onListening()
+ if (this.client.listening) {
+ this._onListening()
} else {
- self.client.once('listening', () => {
- self._onListening()
+ this.client.once('listening', () => {
+ this._onListening()
})
}
}
@@ -281,24 +278,23 @@ class Torrent extends EventEmitter {
}
_onListening () {
- const self = this
- if (self.discovery || self.destroyed) return
+ if (this.discovery || this.destroyed) return
- let trackerOpts = self.client.tracker
+ let trackerOpts = this.client.tracker
if (trackerOpts) {
- trackerOpts = extend(self.client.tracker, {
- getAnnounceOpts () {
+ trackerOpts = extend(this.client.tracker, {
+ getAnnounceOpts: () => {
const opts = {
- uploaded: self.uploaded,
- downloaded: self.downloaded,
- left: Math.max(self.length - self.downloaded, 0)
+ uploaded: this.uploaded,
+ downloaded: this.downloaded,
+ left: Math.max(this.length - this.downloaded, 0)
}
- if (self.client.tracker.getAnnounceOpts) {
- extendMutable(opts, self.client.tracker.getAnnounceOpts())
+ if (this.client.tracker.getAnnounceOpts) {
+ extendMutable(opts, this.client.tracker.getAnnounceOpts())
}
- if (self._getAnnounceOpts) {
+ if (this._getAnnounceOpts) {
// TODO: consider deprecating this, as it's redundant with the former case
- extendMutable(opts, self._getAnnounceOpts())
+ extendMutable(opts, this._getAnnounceOpts())
}
return opts
}
@@ -306,58 +302,54 @@ class Torrent extends EventEmitter {
}
// begin discovering peers via DHT and trackers
- self.discovery = new Discovery({
- infoHash: self.infoHash,
- announce: self.announce,
- peerId: self.client.peerId,
- dht: !self.private && self.client.dht,
+ this.discovery = new Discovery({
+ infoHash: this.infoHash,
+ announce: this.announce,
+ peerId: this.client.peerId,
+ dht: !this.private && this.client.dht,
tracker: trackerOpts,
- port: self.client.torrentPort,
+ port: this.client.torrentPort,
userAgent: USER_AGENT
})
- self.discovery.on('error', onError)
- self.discovery.on('peer', onPeer)
- self.discovery.on('trackerAnnounce', onTrackerAnnounce)
- self.discovery.on('dhtAnnounce', onDHTAnnounce)
- self.discovery.on('warning', onWarning)
-
- function onError (err) {
- self._destroy(err)
- }
+ this.discovery.on('error', (err) => {
+ this._destroy(err)
+ })
- function onPeer (peer) {
+ this.discovery.on('peer', (peer) => {
// Don't create new outgoing TCP connections when torrent is done
- if (typeof peer === 'string' && self.done) return
- self.addPeer(peer)
- }
+ if (typeof peer === 'string' && this.done) return
+ this.addPeer(peer)
+ })
- function onTrackerAnnounce () {
- self.emit('trackerAnnounce')
- if (self.numPeers === 0) self.emit('noPeers', 'tracker')
- }
+ this.discovery.on('trackerAnnounce', () => {
+ this.emit('trackerAnnounce')
+ if (this.numPeers === 0) this.emit('noPeers', 'tracker')
+ })
- function onDHTAnnounce () {
- self.emit('dhtAnnounce')
- if (self.numPeers === 0) self.emit('noPeers', 'dht')
- }
+ this.discovery.on('dhtAnnounce', () => {
+ this.emit('dhtAnnounce')
+ if (this.numPeers === 0) this.emit('noPeers', 'dht')
+ })
- function onWarning (err) {
- self.emit('warning', err)
- }
+ this.discovery.on('warning', (err) => {
+ this.emit('warning', err)
+ })
- if (self.info) {
+ if (this.info) {
// if full metadata was included in initial torrent id, use it immediately. Otherwise,
// wait for torrent-discovery to find peers and ut_metadata to get the metadata.
- self._onMetadata(self)
- } else if (self.xs) {
- self._getMetadataFromServer()
+ this._onMetadata(this)
+ } else if (this.xs) {
+ this._getMetadataFromServer()
}
}
_getMetadataFromServer () {
+ // to allow function hoisting
const self = this
- const urls = Array.isArray(self.xs) ? self.xs : [ self.xs ]
+
+ const urls = Array.isArray(this.xs) ? this.xs : [ this.xs ]
const tasks = urls.map(url => cb => {
getMetadataFromURL(url, cb)
@@ -425,14 +417,13 @@ class Torrent extends EventEmitter {
* Called when the full torrent metadata is received.
*/
_onMetadata (metadata) {
- const self = this
- if (self.metadata || self.destroyed) return
- self._debug('got metadata')
+ if (this.metadata || this.destroyed) return
+ this._debug('got metadata')
- self._xsRequests.forEach(req => {
+ this._xsRequests.forEach(req => {
req.abort()
})
- self._xsRequests = []
+ this._xsRequests = []
let parsedTorrent
if (metadata && metadata.infoHash) {
@@ -442,99 +433,99 @@ class Torrent extends EventEmitter {
try {
parsedTorrent = parseTorrent(metadata)
} catch (err) {
- return self._destroy(err)
+ return this._destroy(err)
}
}
- self._processParsedTorrent(parsedTorrent)
- self.metadata = self.torrentFile
+ this._processParsedTorrent(parsedTorrent)
+ this.metadata = this.torrentFile
// add web seed urls (BEP19)
- if (self.client.enableWebSeeds) {
- self.urlList.forEach(url => {
- self.addWebSeed(url)
+ if (this.client.enableWebSeeds) {
+ this.urlList.forEach(url => {
+ this.addWebSeed(url)
})
}
- self._rarityMap = new RarityMap(self)
+ this._rarityMap = new RarityMap(this)
- self.store = new ImmediateChunkStore(
- new self._store(self.pieceLength, {
+ this.store = new ImmediateChunkStore(
+ new this._store(this.pieceLength, {
torrent: {
- infoHash: self.infoHash
+ infoHash: this.infoHash
},
- files: self.files.map(file => ({
- path: path.join(self.path, file.path),
+ files: this.files.map(file => ({
+ path: path.join(this.path, file.path),
length: file.length,
offset: file.offset
})),
- length: self.length
+ length: this.length
})
)
- self.files = self.files.map(file => new File(self, file))
+ this.files = this.files.map(file => new File(this, file))
// Select only specified files (BEP53) http://www.bittorrent.org/beps/bep_0053.html
- if (self.so) {
- const selectOnlyFiles = parseRange.parse(self.so)
+ if (this.so) {
+ const selectOnlyFiles = parseRange.parse(this.so)
- self.files.forEach((v, i) => {
- if (selectOnlyFiles.includes(i)) self.files[i].select(true)
+ this.files.forEach((v, i) => {
+ if (selectOnlyFiles.includes(i)) this.files[i].select(true)
})
} else {
// start off selecting the entire torrent with low priority
- if (self.pieces.length !== 0) {
- self.select(0, self.pieces.length - 1, false)
+ if (this.pieces.length !== 0) {
+ this.select(0, this.pieces.length - 1, false)
}
}
- self._hashes = self.pieces
+ this._hashes = this.pieces
- self.pieces = self.pieces.map((hash, i) => {
- const pieceLength = (i === self.pieces.length - 1)
- ? self.lastPieceLength
- : self.pieceLength
+ this.pieces = this.pieces.map((hash, i) => {
+ const pieceLength = (i === this.pieces.length - 1)
+ ? this.lastPieceLength
+ : this.pieceLength
return new Piece(pieceLength)
})
- self._reservations = self.pieces.map(() => [])
+ this._reservations = this.pieces.map(() => [])
- self.bitfield = new BitField(self.pieces.length)
+ this.bitfield = new BitField(this.pieces.length)
- self.wires.forEach(wire => {
+ this.wires.forEach(wire => {
// If we didn't have the metadata at the time ut_metadata was initialized for this
// wire, we still want to make it available to the peer in case they request it.
- if (wire.ut_metadata) wire.ut_metadata.setMetadata(self.metadata)
+ if (wire.ut_metadata) wire.ut_metadata.setMetadata(this.metadata)
- self._onWireWithMetadata(wire)
+ this._onWireWithMetadata(wire)
})
- if (self.skipVerify) {
+ if (this.skipVerify) {
// Skip verifying exisitng data and just assume it's correct
- self._markAllVerified()
- self._onStore()
+ this._markAllVerified()
+ this._onStore()
} else {
- self._debug('verifying existing torrent data')
- if (self._fileModtimes && self._store === FSChunkStore) {
+ this._debug('verifying existing torrent data')
+ if (this._fileModtimes && this._store === FSChunkStore) {
// don't verify if the files haven't been modified since we last checked
- self.getFileModtimes((err, fileModtimes) => {
- if (err) return self._destroy(err)
+ this.getFileModtimes((err, fileModtimes) => {
+ if (err) return this._destroy(err)
- const unchanged = self.files.map((_, index) => fileModtimes[index] === self._fileModtimes[index]).every(x => x)
+ const unchanged = this.files.map((_, index) => fileModtimes[index] === this._fileModtimes[index]).every(x => x)
if (unchanged) {
- self._markAllVerified()
- self._onStore()
+ this._markAllVerified()
+ this._onStore()
} else {
- self._verifyPieces()
+ this._verifyPieces()
}
})
} else {
- self._verifyPieces()
+ this._verifyPieces()
}
}
- self.emit('metadata')
+ this.emit('metadata')
}
/*
@@ -543,46 +534,44 @@ class Torrent extends EventEmitter {
* Only valid in Node, not in the browser.
*/
getFileModtimes (cb) {
- const self = this
const ret = []
- parallelLimit(self.files.map((file, index) => cb => {
- fs.stat(path.join(self.path, file.path), (err, stat) => {
+ parallelLimit(this.files.map((file, index) => cb => {
+ fs.stat(path.join(this.path, file.path), (err, stat) => {
if (err && err.code !== 'ENOENT') return cb(err)
ret[index] = stat && stat.mtime.getTime()
cb(null)
})
}), FILESYSTEM_CONCURRENCY, err => {
- self._debug('done getting file modtimes')
+ this._debug('done getting file modtimes')
cb(err, ret)
})
}
_verifyPieces () {
- const self = this
- parallelLimit(self.pieces.map((_, index) => cb => {
- if (self.destroyed) return cb(new Error('torrent is destroyed'))
+ parallelLimit(this.pieces.map((_, index) => cb => {
+ if (this.destroyed) return cb(new Error('torrent is destroyed'))
- self.store.get(index, (err, buf) => {
- if (self.destroyed) return cb(new Error('torrent is destroyed'))
+ this.store.get(index, (err, buf) => {
+ if (this.destroyed) return cb(new Error('torrent is destroyed'))
if (err) return process.nextTick(cb, null) // ignore error
sha1(buf, hash => {
- if (self.destroyed) return cb(new Error('torrent is destroyed'))
+ if (this.destroyed) return cb(new Error('torrent is destroyed'))
- if (hash === self._hashes[index]) {
- if (!self.pieces[index]) return
- self._debug('piece verified %s', index)
- self._markVerified(index)
+ if (hash === this._hashes[index]) {
+ if (!this.pieces[index]) return
+ this._debug('piece verified %s', index)
+ this._markVerified(index)
} else {
- self._debug('piece invalid %s', index)
+ this._debug('piece invalid %s', index)
}
cb(null)
})
})
}), FILESYSTEM_CONCURRENCY, err => {
- if (err) return self._destroy(err)
- self._debug('done verifying')
- self._onStore()
+ if (err) return this._destroy(err)
+ this._debug('done verifying')
+ this._onStore()
})
}
@@ -602,64 +591,61 @@ class Torrent extends EventEmitter {
* Called when the metadata, listening server, and underlying chunk store is initialized.
*/
_onStore () {
- const self = this
- if (self.destroyed) return
- self._debug('on store')
+ if (this.destroyed) return
+ this._debug('on store')
- self.ready = true
- self.emit('ready')
+ this.ready = true
+ this.emit('ready')
// Files may start out done if the file was already in the store
- self._checkDone()
+ this._checkDone()
// In case any selections were made before torrent was ready
- self._updateSelections()
+ this._updateSelections()
}
destroy (cb) {
- const self = this
- self._destroy(null, cb)
+ this._destroy(null, cb)
}
_destroy (err, cb) {
- const self = this
- if (self.destroyed) return
- self.destroyed = true
- self._debug('destroy')
+ if (this.destroyed) return
+ this.destroyed = true
+ this._debug('destroy')
- self.client._remove(self)
+ this.client._remove(this)
- clearInterval(self._rechokeIntervalId)
+ clearInterval(this._rechokeIntervalId)
- self._xsRequests.forEach(req => {
+ this._xsRequests.forEach(req => {
req.abort()
})
- if (self._rarityMap) {
- self._rarityMap.destroy()
+ if (this._rarityMap) {
+ this._rarityMap.destroy()
}
- for (const id in self._peers) {
- self.removePeer(id)
+ for (const id in this._peers) {
+ this.removePeer(id)
}
- self.files.forEach(file => {
+ this.files.forEach(file => {
if (file instanceof File) file._destroy()
})
- const tasks = self._servers.map(server => cb => {
+ const tasks = this._servers.map(server => cb => {
server.destroy(cb)
})
- if (self.discovery) {
+ if (this.discovery) {
tasks.push(cb => {
- self.discovery.destroy(cb)
+ this.discovery.destroy(cb)
})
}
- if (self.store) {
+ if (this.store) {
tasks.push(cb => {
- self.store.close(cb)
+ this.store.close(cb)
})
}
@@ -673,39 +659,38 @@ class Torrent extends EventEmitter {
// errors versus torrent errors. Torrent errors are not fatal, and the client
// is still usable afterwards. Therefore, always listen for errors in both
// places (`client.on('error')` and `torrent.on('error')`).
- if (self.listenerCount('error') === 0) {
- self.client.emit('error', err)
+ if (this.listenerCount('error') === 0) {
+ this.client.emit('error', err)
} else {
- self.emit('error', err)
+ this.emit('error', err)
}
}
- self.emit('close')
+ this.emit('close')
- self.client = null
- self.files = []
- self.discovery = null
- self.store = null
- self._rarityMap = null
- self._peers = null
- self._servers = null
- self._xsRequests = null
+ this.client = null
+ this.files = []
+ this.discovery = null
+ this.store = null
+ this._rarityMap = null
+ this._peers = null
+ this._servers = null
+ this._xsRequests = null
}
addPeer (peer) {
- const self = this
- if (self.destroyed) throw new Error('torrent is destroyed')
- if (!self.infoHash) throw new Error('addPeer() must not be called before the `infoHash` event')
+ if (this.destroyed) throw new Error('torrent is destroyed')
+ if (!this.infoHash) throw new Error('addPeer() must not be called before the `infoHash` event')
- if (self.client.blocked) {
+ if (this.client.blocked) {
let host
if (typeof peer === 'string') {
let parts
try {
parts = addrToIPPort(peer)
} catch (e) {
- self._debug('ignoring peer: invalid %s', peer)
- self.emit('invalidPeer', peer)
+ this._debug('ignoring peer: invalid %s', peer)
+ this.emit('invalidPeer', peer)
return false
}
host = parts[0]
@@ -713,65 +698,64 @@ class Torrent extends EventEmitter {
host = peer.remoteAddress
}
- if (host && self.client.blocked.contains(host)) {
- self._debug('ignoring peer: blocked %s', peer)
+ if (host && this.client.blocked.contains(host)) {
+ this._debug('ignoring peer: blocked %s', peer)
if (typeof peer !== 'string') peer.destroy()
- self.emit('blockedPeer', peer)
+ this.emit('blockedPeer', peer)
return false
}
}
- const wasAdded = !!self._addPeer(peer)
+ const wasAdded = !!this._addPeer(peer)
if (wasAdded) {
- self.emit('peer', peer)
+ this.emit('peer', peer)
} else {
- self.emit('invalidPeer', peer)
+ this.emit('invalidPeer', peer)
}
return wasAdded
}
_addPeer (peer) {
- const self = this
- if (self.destroyed) {
+ if (this.destroyed) {
if (typeof peer !== 'string') peer.destroy()
return null
}
- if (typeof peer === 'string' && !self._validAddr(peer)) {
- self._debug('ignoring peer: invalid %s', peer)
+ if (typeof peer === 'string' && !this._validAddr(peer)) {
+ this._debug('ignoring peer: invalid %s', peer)
return null
}
const id = (peer && peer.id) || peer
- if (self._peers[id]) {
- self._debug('ignoring peer: duplicate (%s)', id)
+ if (this._peers[id]) {
+ this._debug('ignoring peer: duplicate (%s)', id)
if (typeof peer !== 'string') peer.destroy()
return null
}
- if (self.paused) {
- self._debug('ignoring peer: torrent is paused')
+ if (this.paused) {
+ this._debug('ignoring peer: torrent is paused')
if (typeof peer !== 'string') peer.destroy()
return null
}
- self._debug('add peer %s', id)
+ this._debug('add peer %s', id)
let newPeer
if (typeof peer === 'string') {
// `peer` is an addr ("ip:port" string)
- newPeer = Peer.createTCPOutgoingPeer(peer, self)
+ newPeer = Peer.createTCPOutgoingPeer(peer, this)
} else {
// `peer` is a WebRTC connection (simple-peer)
- newPeer = Peer.createWebRTCPeer(peer, self)
+ newPeer = Peer.createWebRTCPeer(peer, this)
}
- self._peers[newPeer.id] = newPeer
- self._peersLength += 1
+ this._peers[newPeer.id] = newPeer
+ this._peersLength += 1
if (typeof peer === 'string') {
// `peer` is an addr ("ip:port" string)
- self._queue.push(newPeer)
- self._drain()
+ this._queue.push(newPeer)
+ this._drain()
}
return newPeer
@@ -806,46 +790,43 @@ class Torrent extends EventEmitter {
* peer that has already sent a handshake.
*/
_addIncomingPeer (peer) {
- const self = this
- if (self.destroyed) return peer.destroy(new Error('torrent is destroyed'))
- if (self.paused) return peer.destroy(new Error('torrent is paused'))
+ if (this.destroyed) return peer.destroy(new Error('torrent is destroyed'))
+ if (this.paused) return peer.destroy(new Error('torrent is paused'))
this._debug('add incoming peer %s', peer.id)
- self._peers[peer.id] = peer
- self._peersLength += 1
+ this._peers[peer.id] = peer
+ this._peersLength += 1
}
removePeer (peer) {
- const self = this
const id = (peer && peer.id) || peer
- peer = self._peers[id]
+ peer = this._peers[id]
if (!peer) return
this._debug('removePeer %s', id)
- delete self._peers[id]
- self._peersLength -= 1
+ delete this._peers[id]
+ this._peersLength -= 1
peer.destroy()
// If torrent swarm was at capacity before, try to open a new connection now
- self._drain()
+ this._drain()
}
select (start, end, priority, notify) {
- const self = this
- if (self.destroyed) throw new Error('torrent is destroyed')
+ if (this.destroyed) throw new Error('torrent is destroyed')
- if (start < 0 || end < start || self.pieces.length <= end) {
+ if (start < 0 || end < start || this.pieces.length <= end) {
throw new Error('invalid selection ', start, ':', end)
}
priority = Number(priority) || 0
- self._debug('select %s-%s (priority %s)', start, end, priority)
+ this._debug('select %s-%s (priority %s)', start, end, priority)
- self._selections.push({
+ this._selections.push({
from: start,
to: end,
offset: 0,
@@ -853,65 +834,62 @@ class Torrent extends EventEmitter {
notify: notify || noop
})
- self._selections.sort((a, b) => b.priority - a.priority)
+ this._selections.sort((a, b) => b.priority - a.priority)
- self._updateSelections()
+ this._updateSelections()
}
deselect (start, end, priority) {
- const self = this
- if (self.destroyed) throw new Error('torrent is destroyed')
+ if (this.destroyed) throw new Error('torrent is destroyed')
priority = Number(priority) || 0
- self._debug('deselect %s-%s (priority %s)', start, end, priority)
+ this._debug('deselect %s-%s (priority %s)', start, end, priority)
- for (let i = 0; i < self._selections.length; ++i) {
- const s = self._selections[i]
+ for (let i = 0; i < this._selections.length; ++i) {
+ const s = this._selections[i]
if (s.from === start && s.to === end && s.priority === priority) {
- self._selections.splice(i, 1)
+ this._selections.splice(i, 1)
break
}
}
- self._updateSelections()
+ this._updateSelections()
}
critical (start, end) {
- const self = this
- if (self.destroyed) throw new Error('torrent is destroyed')
+ if (this.destroyed) throw new Error('torrent is destroyed')
- self._debug('critical %s-%s', start, end)
+ this._debug('critical %s-%s', start, end)
for (let i = start; i <= end; ++i) {
- self._critical[i] = true
+ this._critical[i] = true
}
- self._updateSelections()
+ this._updateSelections()
}
_onWire (wire, addr) {
- const self = this
- self._debug('got wire %s (%s)', wire._debugId, addr || 'Unknown')
+ this._debug('got wire %s (%s)', wire._debugId, addr || 'Unknown')
wire.on('download', downloaded => {
- if (self.destroyed) return
- self.received += downloaded
- self._downloadSpeed(downloaded)
- self.client._downloadSpeed(downloaded)
- self.emit('download', downloaded)
- self.client.emit('download', downloaded)
+ if (this.destroyed) return
+ this.received += downloaded
+ this._downloadSpeed(downloaded)
+ this.client._downloadSpeed(downloaded)
+ this.emit('download', downloaded)
+ this.client.emit('download', downloaded)
})
wire.on('upload', uploaded => {
- if (self.destroyed) return
- self.uploaded += uploaded
- self._uploadSpeed(uploaded)
- self.client._uploadSpeed(uploaded)
- self.emit('upload', uploaded)
- self.client.emit('upload', uploaded)
+ if (this.destroyed) return
+ this.uploaded += uploaded
+ this._uploadSpeed(uploaded)
+ this.client._uploadSpeed(uploaded)
+ this.emit('upload', uploaded)
+ this.client.emit('upload', uploaded)
})
- self.wires.push(wire)
+ this.wires.push(wire)
if (addr) {
// Sometimes RTCPeerConnection.getStats() doesn't return an ip:port for peers
@@ -921,25 +899,25 @@ class Torrent extends EventEmitter {
}
// When peer sends PORT message, add that DHT node to routing table
- if (self.client.dht && self.client.dht.listening) {
+ if (this.client.dht && this.client.dht.listening) {
wire.on('port', port => {
- if (self.destroyed || self.client.dht.destroyed) {
+ if (this.destroyed || this.client.dht.destroyed) {
return
}
if (!wire.remoteAddress) {
- return self._debug('ignoring PORT from peer with no address')
+ return this._debug('ignoring PORT from peer with no address')
}
if (port === 0 || port > 65536) {
- return self._debug('ignoring invalid PORT from peer')
+ return this._debug('ignoring invalid PORT from peer')
}
- self._debug('port: %s (from %s)', port, addr)
- self.client.dht.addNode({ host: wire.remoteAddress, port })
+ this._debug('port: %s (from %s)', port, addr)
+ this.client.dht.addNode({ host: wire.remoteAddress, port })
})
}
wire.on('timeout', () => {
- self._debug('wire timeout (%s)', addr)
+ this._debug('wire timeout (%s)', addr)
// TODO: this might be destroying wires too eagerly
wire.destroy()
})
@@ -951,38 +929,38 @@ class Torrent extends EventEmitter {
wire.setKeepAlive(true)
// use ut_metadata extension
- wire.use(utMetadata(self.metadata))
+ wire.use(utMetadata(this.metadata))
wire.ut_metadata.on('warning', err => {
- self._debug('ut_metadata warning: %s', err.message)
+ this._debug('ut_metadata warning: %s', err.message)
})
- if (!self.metadata) {
+ if (!this.metadata) {
wire.ut_metadata.on('metadata', metadata => {
- self._debug('got metadata via ut_metadata')
- self._onMetadata(metadata)
+ this._debug('got metadata via ut_metadata')
+ this._onMetadata(metadata)
})
wire.ut_metadata.fetch()
}
// use ut_pex extension if the torrent is not flagged as private
- if (typeof utPex === 'function' && !self.private) {
+ if (typeof utPex === 'function' && !this.private) {
wire.use(utPex())
wire.ut_pex.on('peer', peer => {
// Only add potential new peers when we're not seeding
- if (self.done) return
- self._debug('ut_pex: got peer: %s (from %s)', peer, addr)
- self.addPeer(peer)
+ if (this.done) return
+ this._debug('ut_pex: got peer: %s (from %s)', peer, addr)
+ this.addPeer(peer)
})
wire.ut_pex.on('dropped', peer => {
// the remote peer believes a given peer has been dropped from the torrent swarm.
// if we're not currently connected to it, then remove it from the queue.
- const peerObj = self._peers[peer]
+ const peerObj = this._peers[peer]
if (peerObj && !peerObj.connected) {
- self._debug('ut_pex: dropped peer: %s (from %s)', peer, addr)
- self.removePeer(peer)
+ this._debug('ut_pex: dropped peer: %s (from %s)', peer, addr)
+ this.removePeer(peer)
}
})
@@ -994,25 +972,24 @@ class Torrent extends EventEmitter {
// Hook to allow user-defined `bittorrent-protocol` extensions
// More info: https://github.com/webtorrent/bittorrent-protocol#extension-api
- self.emit('wire', wire, addr)
+ this.emit('wire', wire, addr)
- if (self.metadata) {
+ if (this.metadata) {
process.nextTick(() => {
// This allows wire.handshake() to be called (by Peer.onHandshake) before any
// messages get sent on the wire
- self._onWireWithMetadata(wire)
+ this._onWireWithMetadata(wire)
})
}
}
_onWireWithMetadata (wire) {
- const self = this
let timeoutId = null
- function onChokeTimeout () {
- if (self.destroyed || wire.destroyed) return
+ const onChokeTimeout = () => {
+ if (this.destroyed || wire.destroyed) return
- if (self._numQueued > 2 * (self._numConns - self.numPeers) &&
+ if (this._numQueued > 2 * (this._numConns - this.numPeers) &&
wire.amInterested) {
wire.destroy()
} else {
@@ -1022,9 +999,9 @@ class Torrent extends EventEmitter {
}
let i
- function updateSeedStatus () {
- if (wire.peerPieces.buffer.length !== self.bitfield.buffer.length) return
- for (i = 0; i < self.pieces.length; ++i) {
+ const updateSeedStatus = () => {
+ if (wire.peerPieces.buffer.length !== this.bitfield.buffer.length) return
+ for (i = 0; i < this.pieces.length; ++i) {
if (!wire.peerPieces.get(i)) return
}
wire.isSeeder = true
@@ -1033,12 +1010,12 @@ class Torrent extends EventEmitter {
wire.on('bitfield', () => {
updateSeedStatus()
- self._update()
+ this._update()
})
wire.on('have', () => {
updateSeedStatus()
- self._update()
+ this._update()
})
wire.once('interested', () => {
@@ -1057,7 +1034,7 @@ class Torrent extends EventEmitter {
wire.on('unchoke', () => {
clearTimeout(timeoutId)
- self._update()
+ this._update()
})
wire.on('request', (index, offset, length, cb) => {
@@ -1065,16 +1042,16 @@ class Torrent extends EventEmitter {
// Per spec, disconnect from peers that request >128KB
return wire.destroy()
}
- if (self.pieces[index]) return
- self.store.get(index, { offset, length }, cb)
+ if (this.pieces[index]) return
+ this.store.get(index, { offset, length }, cb)
})
- wire.bitfield(self.bitfield) // always send bitfield (required)
+ wire.bitfield(this.bitfield) // always send bitfield (required)
wire.uninterested() // always start out uninterested (as per protocol)
// Send PORT message to peers that support DHT
- if (wire.peerExtensions.dht && self.client.dht && self.client.dht.listening) {
- wire.port(self.client.dht.address().port)
+ if (wire.peerExtensions.dht && this.client.dht && this.client.dht.listening) {
+ wire.port(this.client.dht.address().port)
}
if (wire.type !== 'webSeed') { // do not choke on webseeds
@@ -1090,58 +1067,53 @@ class Torrent extends EventEmitter {
* Called on selection changes.
*/
_updateSelections () {
- const self = this
- if (!self.ready || self.destroyed) return
+ if (!this.ready || this.destroyed) return
process.nextTick(() => {
- self._gcSelections()
+ this._gcSelections()
})
- self._updateInterest()
- self._update()
+ this._updateInterest()
+ this._update()
}
/**
* Garbage collect selections with respect to the store's current state.
*/
_gcSelections () {
- const self = this
-
- for (let i = 0; i < self._selections.length; ++i) {
- const s = self._selections[i]
+ for (let i = 0; i < this._selections.length; ++i) {
+ const s = this._selections[i]
const oldOffset = s.offset
// check for newly downloaded pieces in selection
- while (self.bitfield.get(s.from + s.offset) && s.from + s.offset < s.to) {
+ while (this.bitfield.get(s.from + s.offset) && s.from + s.offset < s.to) {
s.offset += 1
}
if (oldOffset !== s.offset) s.notify()
if (s.to !== s.from + s.offset) continue
- if (!self.bitfield.get(s.from + s.offset)) continue
+ if (!this.bitfield.get(s.from + s.offset)) continue
- self._selections.splice(i, 1) // remove fully downloaded selection
+ this._selections.splice(i, 1) // remove fully downloaded selection
i -= 1 // decrement i to offset splice
s.notify()
- self._updateInterest()
+ this._updateInterest()
}
- if (!self._selections.length) self.emit('idle')
+ if (!this._selections.length) this.emit('idle')
}
/**
* Update interested status for all peers.
*/
_updateInterest () {
- const self = this
+ const prev = this._amInterested
+ this._amInterested = !!this._selections.length
- const prev = self._amInterested
- self._amInterested = !!self._selections.length
-
- self.wires.forEach(wire => {
+ this.wires.forEach(wire => {
let interested = false
- for (let index = 0; index < self.pieces.length; ++index) {
- if (self.pieces[index] && wire.peerPieces.get(index)) {
+ for (let index = 0; index < this.pieces.length; ++index) {
+ if (this.pieces[index] && wire.peerPieces.get(index)) {
interested = true
break
}
@@ -1151,23 +1123,22 @@ class Torrent extends EventEmitter {
else wire.uninterested()
})
- if (prev === self._amInterested) return
- if (self._amInterested) self.emit('interested')
- else self.emit('uninterested')
+ if (prev === this._amInterested) return
+ if (this._amInterested) this.emit('interested')
+ else this.emit('uninterested')
}
/**
* Heartbeat to update all peers and their requests.
*/
_update () {
- const self = this
- if (self.destroyed) return
+ if (this.destroyed) return
// update wires in random order for better request distribution
- const ite = randomIterate(self.wires)
+ const ite = randomIterate(this.wires)
let wire
while ((wire = ite())) {
- self._updateWire(wire)
+ this._updateWire(wire)
}
}
@@ -1175,6 +1146,7 @@ class Torrent extends EventEmitter {
* Attempts to update a peer's requests
*/
_updateWire (wire) {
+ // to allow function hoisting
const self = this
if (wire.peerChoking) return
@@ -1321,16 +1293,15 @@ class Torrent extends EventEmitter {
* unchoking as described in BEP3.
*/
_rechoke () {
- const self = this
- if (!self.ready) return
+ if (!this.ready) return
- if (self._rechokeOptimisticTime > 0) self._rechokeOptimisticTime -= 1
- else self._rechokeOptimisticWire = null
+ if (this._rechokeOptimisticTime > 0) this._rechokeOptimisticTime -= 1
+ else this._rechokeOptimisticWire = null
const peers = []
- self.wires.forEach(wire => {
- if (!wire.isSeeder && wire !== self._rechokeOptimisticWire) {
+ this.wires.forEach(wire => {
+ if (!wire.isSeeder && wire !== this._rechokeOptimisticWire) {
peers.push({
wire,
downloadSpeed: wire.downloadSpeed(),
@@ -1345,20 +1316,20 @@ class Torrent extends EventEmitter {
let unchokeInterested = 0
let i = 0
- for (; i < peers.length && unchokeInterested < self._rechokeNumSlots; ++i) {
+ for (; i < peers.length && unchokeInterested < this._rechokeNumSlots; ++i) {
peers[i].isChoked = false
if (peers[i].wire.peerInterested) unchokeInterested += 1
}
// Optimistically unchoke a peer
- if (!self._rechokeOptimisticWire && i < peers.length && self._rechokeNumSlots) {
+ if (!this._rechokeOptimisticWire && i < peers.length && this._rechokeNumSlots) {
const candidates = peers.slice(i).filter(peer => peer.wire.peerInterested)
const optimistic = candidates[randomInt(candidates.length)]
if (optimistic) {
optimistic.isChoked = false
- self._rechokeOptimisticWire = optimistic.wire
- self._rechokeOptimisticTime = RECHOKE_OPTIMISTIC_DURATION
+ this._rechokeOptimisticWire = optimistic.wire
+ this._rechokeOptimisticTime = RECHOKE_OPTIMISTIC_DURATION
}
}
@@ -1396,13 +1367,11 @@ class Torrent extends EventEmitter {
* given wire may effectively swap out the request for one of its own.
*/
_hotswap (wire, index) {
- const self = this
-
const speed = wire.downloadSpeed()
if (speed < Piece.BLOCK_LENGTH) return false
- if (!self._reservations[index]) return false
+ if (!this._reservations[index]) return false
- const r = self._reservations[index]
+ const r = this._reservations[index]
if (!r) {
return false
}
@@ -1433,10 +1402,10 @@ class Torrent extends EventEmitter {
const req = minWire.requests[i]
if (req.piece !== index) continue
- self.pieces[index].cancel((req.offset / Piece.BLOCK_LENGTH) | 0)
+ this.pieces[index].cancel((req.offset / Piece.BLOCK_LENGTH) | 0)
}
- self.emit('hotswap', minWire, wire, index)
+ this.emit('hotswap', minWire, wire, index)
return true
}
@@ -1545,58 +1514,56 @@ class Torrent extends EventEmitter {
}
_checkDone () {
- const self = this
- if (self.destroyed) return
+ if (this.destroyed) return
// are any new files done?
- self.files.forEach(file => {
+ this.files.forEach(file => {
if (file.done) return
for (let i = file._startPiece; i <= file._endPiece; ++i) {
- if (!self.bitfield.get(i)) return
+ if (!this.bitfield.get(i)) return
}
file.done = true
file.emit('done')
- self._debug(`file done: ${file.name}`)
+ this._debug(`file done: ${file.name}`)
})
// is the torrent done? (if all current selections are satisfied, or there are
// no selections, then torrent is done)
let done = true
- for (let i = 0; i < self._selections.length; i++) {
- const selection = self._selections[i]
+ for (let i = 0; i < this._selections.length; i++) {
+ const selection = this._selections[i]
for (let piece = selection.from; piece <= selection.to; piece++) {
- if (!self.bitfield.get(piece)) {
+ if (!this.bitfield.get(piece)) {
done = false
break
}
}
if (!done) break
}
- if (!self.done && done) {
- self.done = true
- self._debug(`torrent done: ${self.infoHash}`)
- self.emit('done')
+ if (!this.done && done) {
+ this.done = true
+ this._debug(`torrent done: ${this.infoHash}`)
+ this.emit('done')
}
- self._gcSelections()
+ this._gcSelections()
return done
}
load (streams, cb) {
- const self = this
- if (self.destroyed) throw new Error('torrent is destroyed')
- if (!self.ready) return self.once('ready', () => { self.load(streams, cb) })
+ if (this.destroyed) throw new Error('torrent is destroyed')
+ if (!this.ready) return this.once('ready', () => { this.load(streams, cb) })
if (!Array.isArray(streams)) streams = [ streams ]
if (!cb) cb = noop
const readable = new MultiStream(streams)
- const writable = new ChunkStoreWriteStream(self.store, self.pieceLength)
+ const writable = new ChunkStoreWriteStream(this.store, this.pieceLength)
pump(readable, writable, err => {
if (err) return cb(err)
- self._markAllVerified()
- self._checkDone()
+ this._markAllVerified()
+ this._checkDone()
cb(null)
})
}
@@ -1635,15 +1602,14 @@ class Torrent extends EventEmitter {
* queue until another connection closes.
*/
_drain () {
- const self = this
- this._debug('_drain numConns %s maxConns %s', self._numConns, self.client.maxConns)
- if (typeof net.connect !== 'function' || self.destroyed || self.paused ||
- self._numConns >= self.client.maxConns) {
+ this._debug('_drain numConns %s maxConns %s', this._numConns, this.client.maxConns)
+ if (typeof net.connect !== 'function' || this.destroyed || this.paused ||
+ this._numConns >= this.client.maxConns) {
return
}
- this._debug('drain (%s queued, %s/%s peers)', self._numQueued, self.numPeers, self.client.maxConns)
+ this._debug('drain (%s queued, %s/%s peers)', this._numQueued, this.numPeers, this.client.maxConns)
- const peer = self._queue.shift()
+ const peer = this._queue.shift()
if (!peer) return // queue could be empty
this._debug('tcp connect attempt to %s', peer.addr)
@@ -1662,12 +1628,12 @@ class Torrent extends EventEmitter {
// When connection closes, attempt reconnect after timeout (with exponential backoff)
conn.on('close', () => {
- if (self.destroyed) return
+ if (this.destroyed) return
// TODO: If torrent is done, do not try to reconnect after a timeout
if (peer.retries >= RECONNECT_WAIT.length) {
- self._debug(
+ this._debug(
'conn %s closed: will not re-add (max %s attempts)',
peer.addr, RECONNECT_WAIT.length
)
@@ -1675,13 +1641,13 @@ class Torrent extends EventEmitter {
}
const ms = RECONNECT_WAIT[peer.retries]
- self._debug(
+ this._debug(
'conn %s closed: will re-add to queue in %sms (attempt %s)',
peer.addr, ms, peer.retries + 1
)
- const reconnectTimeout = setTimeout(function reconnectTimeout () {
- const newPeer = self._addPeer(peer.addr)
+ const reconnectTimeout = setTimeout(() => {
+ const newPeer = this._addPeer(peer.addr)
if (newPeer) newPeer.retries = peer.retries + 1
}, ms)
if (reconnectTimeout.unref) reconnectTimeout.unref()