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:
authorPaul-Louis Ageneau <paul-louis@ageneau.org>2022-01-18 00:03:39 +0300
committerGitHub <noreply@github.com>2022-01-18 00:03:39 +0300
commit4f02de3a445f3a9eb46c49a8964c9660bdf6e5d7 (patch)
treec447950ff85ed20d0de9c8445b8c80bac143e2b4 /lib
parentfdff1c9769eb812dca9135c1f62538b27360c38c (diff)
feat: add BEP6 Fast Extension support (#2243)
* chore: bump bittorrent-protocol to ^3.5.0 * feat: implement BEP6 Fast Extension
Diffstat (limited to 'lib')
-rw-r--r--lib/peer.js3
-rw-r--r--lib/torrent.js80
2 files changed, 78 insertions, 5 deletions
diff --git a/lib/peer.js b/lib/peer.js
index 19cb5ff..4c63269 100644
--- a/lib/peer.js
+++ b/lib/peer.js
@@ -327,7 +327,8 @@ class Peer extends EventEmitter {
handshake () {
const opts = {
- dht: this.swarm.private ? false : !!this.swarm.client.dht
+ dht: this.swarm.private ? false : !!this.swarm.client.dht,
+ fast: true
}
this.wire.handshake(this.swarm.infoHash, this.swarm.client.peerId, opts)
this.sentHandshake = true
diff --git a/lib/torrent.js b/lib/torrent.js
index ac7cb97..1bb0062 100644
--- a/lib/torrent.js
+++ b/lib/torrent.js
@@ -650,6 +650,28 @@ class Torrent extends EventEmitter {
this.bitfield.set(index, true)
}
+ _hasAllPieces () {
+ for (let index = 0; index < this.pieces.length; index++) {
+ if (!this.bitfield.get(index)) return false
+ }
+ return true
+ }
+
+ _hasNoPieces () {
+ return !this._hasMorePieces(0)
+ }
+
+ _hasMorePieces (threshold) {
+ let count = 0
+ for (let index = 0; index < this.pieces.length; index++) {
+ if (this.bitfield.get(index)) {
+ count += 1
+ if (count > threshold) return true
+ }
+ }
+ return false
+ }
+
/**
* Called when the metadata, listening server, and underlying chunk store is initialized.
*/
@@ -1139,6 +1161,26 @@ class Torrent extends EventEmitter {
this._updateWireInterest(wire)
})
+ // fast extension (BEP6)
+ wire.on('have-all', () => {
+ wire.isSeeder = true
+ wire.choke() // always choke seeders
+ this._update()
+ this._updateWireInterest(wire)
+ })
+
+ // fast extension (BEP6)
+ wire.on('have-none', () => {
+ wire.isSeeder = false
+ this._update()
+ this._updateWireInterest(wire)
+ })
+
+ // fast extension (BEP6)
+ wire.on('allowed-fast', (index) => {
+ this._update()
+ })
+
wire.once('interested', () => {
wire.unchoke()
})
@@ -1167,7 +1209,10 @@ class Torrent extends EventEmitter {
this.store.get(index, { offset, length }, cb)
})
- wire.bitfield(this.bitfield) // always send bitfield (required)
+ // always send bitfield or equivalent fast extension message (required)
+ if (wire.hasFast && this._hasAllPieces()) wire.haveAll()
+ else if (wire.hasFast && this._hasNoPieces()) wire.haveNone()
+ else wire.bitfield(this.bitfield)
// initialize interest in case bitfield message was already received before above handler was registered
this._updateWireInterest(wire)
@@ -1284,15 +1329,42 @@ class Torrent extends EventEmitter {
// to allow function hoisting
const self = this
- if (wire.peerChoking) return
- if (!wire.downloaded) return validateWire()
-
const minOutstandingRequests = getBlockPipelineLength(wire, PIPELINE_MIN_DURATION)
if (wire.requests.length >= minOutstandingRequests) return
const maxOutstandingRequests = getBlockPipelineLength(wire, PIPELINE_MAX_DURATION)
+ if (wire.peerChoking) {
+ if (wire.hasFast && wire.peerAllowedFastSet.length > 0 &&
+ !this._hasMorePieces(wire.peerAllowedFastSet.length - 1)) {
+ requestAllowedFastSet()
+ }
+ return
+ }
+
+ if (!wire.downloaded) return validateWire()
+
trySelectWire(false) || trySelectWire(true)
+ function requestAllowedFastSet () {
+ if (wire.requests.length >= maxOutstandingRequests) return false
+
+ for (const piece of wire.peerAllowedFastSet) {
+ if (wire.peerPieces.get(piece) && !self.bitfield.get(piece)) {
+ while (self._request(wire, piece, false) &&
+ wire.requests.length < maxOutstandingRequests) {
+ // body intentionally empty
+ // request all non-reserved blocks in this piece
+ }
+ }
+
+ if (wire.requests.length < maxOutstandingRequests) continue
+
+ return true
+ }
+
+ return false
+ }
+
function genPieceFilterFunc (start, end, tried, rank) {
return i => i >= start && i <= end && !(i in tried) && wire.peerPieces.get(i) && (!rank || rank(i))
}