diff options
-rw-r--r-- | lib/torrent.js | 13 | ||||
-rw-r--r-- | lib/webconn.js | 30 | ||||
-rw-r--r-- | package.json | 1 |
3 files changed, 40 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}`)) } diff --git a/package.json b/package.json index 882055a..ebe8d31 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "http-node": "github:feross/http-node#webtorrent", "immediate-chunk-store": "^2.1.1", "load-ip-set": "^2.1.2", + "lt_donthave": "^1.0.1", "memory-chunk-store": "^1.3.1", "mime": "^2.5.0", "multistream": "^4.1.0", |