diff options
author | Feross Aboukhadijeh <feross@feross.org> | 2021-04-14 05:15:21 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-14 05:15:21 +0300 |
commit | ee9da3d019742b648ec87c7757a25c8320cb2f3d (patch) | |
tree | f2747fb7a8ffa681b6e6481ebaef1d0d9596d400 /lib | |
parent | c780b45154d746c7d2fc94c01566a23967d3bddb (diff) | |
parent | dcde609fffd1b7e66f7ea4881e8838d9f5915ec2 (diff) |
Merge pull request #2025 from jhiesey/lt_donthave
Diffstat (limited to 'lib')
-rw-r--r-- | lib/torrent.js | 13 | ||||
-rw-r--r-- | lib/webconn.js | 30 |
2 files changed, 39 insertions, 4 deletions
diff --git a/lib/torrent.js b/lib/torrent.js index ca58842..c87c079 100644 --- a/lib/torrent.js +++ b/lib/torrent.js @@ -11,6 +11,7 @@ const fs = require('fs') const FSChunkStore = require('fs-chunk-store') // browser: `memory-chunk-store` const get = require('simple-get') const ImmediateChunkStore = require('immediate-chunk-store') +const ltDontHave = require('lt_donthave') const MultiStream = require('multistream') const net = require('net') // browser exclude const os = require('os') // browser exclude @@ -1012,7 +1013,9 @@ class Torrent extends EventEmitter { }) // Timeout for piece requests to this peer - wire.setTimeout(PIECE_TIMEOUT, true) + if (wire.type !== 'webSeed') { // webseeds always send 'unhave' on http timeout + wire.setTimeout(PIECE_TIMEOUT, true) + } // Send KEEP-ALIVE (every 60s) so peers will not disconnect the wire wire.setKeepAlive(true) @@ -1059,6 +1062,8 @@ class Torrent extends EventEmitter { }) } + wire.use(ltDontHave()) + // Hook to allow user-defined `bittorrent-protocol` extensions // More info: https://github.com/webtorrent/bittorrent-protocol#extension-api this.emit('wire', wire, addr) @@ -1109,6 +1114,12 @@ class Torrent extends EventEmitter { this._updateWireInterest(wire) }) + wire.lt_donthave.on('donthave', () => { + updateSeedStatus() + this._update() + this._updateWireInterest(wire) + }) + wire.once('interested', () => { wire.unchoke() }) diff --git a/lib/webconn.js b/lib/webconn.js index a2c24a4..c957fbb 100644 --- a/lib/webconn.js +++ b/lib/webconn.js @@ -1,11 +1,15 @@ const BitField = require('bitfield').default const debug = require('debug')('webtorrent:webconn') const get = require('simple-get') +const ltDontHave = require('lt_donthave') const sha1 = require('simple-sha1') const Wire = require('bittorrent-protocol') const VERSION = require('../package.json').version +const SOCKET_TIMEOUT = 60000 +const RETRY_DELAY = 10000 + /** * Converts requests for torrent blocks into http range requests. * @param {string} url web seed url @@ -26,6 +30,8 @@ class WebConn extends Wire { _init () { this.setKeepAlive(true) + this.use(ltDontHave()) + this.once('handshake', (infoHash, peerId) => { if (this.destroyed) return this.handshake(infoHash, this.webPeerId) @@ -46,10 +52,26 @@ class WebConn extends Wire { this.on('choke', () => { debug('choke') }) this.on('unchoke', () => { debug('unchoke') }) this.on('bitfield', () => { debug('bitfield') }) + this.lt_donthave.on('donthave', () => { debug('donthave') }) this.on('request', (pieceIndex, offset, length, callback) => { debug('request pieceIndex=%d offset=%d length=%d', pieceIndex, offset, length) - this.httpRequest(pieceIndex, offset, length, callback) + this.httpRequest(pieceIndex, offset, length, (err, data) => { + if (err) { + // Cancel all in progress requests for this piece + this.lt_donthave.donthave(pieceIndex) + + // Wait a little while before saying the webseed has the failed piece again + const retryTimeout = setTimeout(() => { + if (this.destroyed) return + + this.have(pieceIndex) + }, RETRY_DELAY) + if (retryTimeout.unref) retryTimeout.unref() + } + + callback(err, data) + }) }) } @@ -74,7 +96,7 @@ class WebConn extends Wire { return file.offset <= rangeEnd && (file.offset + file.length) > rangeStart }) if (requestedFiles.length < 1) { - return cb(new Error('Could not find file corresponnding to web seed range request')) + return cb(new Error('Could not find file corresponding to web seed range request')) } requests = requestedFiles.map(requestedFile => { @@ -116,10 +138,12 @@ class WebConn extends Wire { headers: { 'user-agent': `WebTorrent/${VERSION} (https://webtorrent.io)`, range: `bytes=${start}-${end}` - } + }, + timeout: SOCKET_TIMEOUT } function onResponse (res, data) { if (res.statusCode < 200 || res.statusCode >= 300) { + if (hasError) return hasError = true return cb(new Error(`Unexpected HTTP status code ${res.statusCode}`)) } |