From dddd652ac29eb6547761bb84a8d6c624bc1152bd Mon Sep 17 00:00:00 2001 From: John Hiesey Date: Thu, 8 Apr 2021 21:08:51 -0700 Subject: Add lt_donthave --- lib/torrent.js | 13 ++++++++++++- lib/webconn.js | 22 ++++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) (limited to 'lib') 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..ca6e0a7 100644 --- a/lib/webconn.js +++ b/lib/webconn.js @@ -1,6 +1,7 @@ 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') @@ -26,6 +27,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 +49,24 @@ 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) => { + // TODO: timeout + + if (err) { + // Cancel all in progress requests for this piece + this.lt_donthave.donthave(pieceIndex) + this.bitfield.set(pieceIndex, false) + + // TODO: delay before re-advertising + this.have(pieceIndex) + } + + callback(err, data) + }) }) } @@ -74,7 +91,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 => { @@ -120,6 +137,7 @@ class WebConn extends Wire { } 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}`)) } -- cgit v1.2.3 From dcde609fffd1b7e66f7ea4881e8838d9f5915ec2 Mon Sep 17 00:00:00 2001 From: John Hiesey Date: Mon, 12 Apr 2021 20:25:27 -0700 Subject: Add timeouts and retry inside webconn --- lib/webconn.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/webconn.js b/lib/webconn.js index ca6e0a7..c957fbb 100644 --- a/lib/webconn.js +++ b/lib/webconn.js @@ -7,6 +7,9 @@ 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 @@ -54,15 +57,17 @@ class WebConn extends Wire { this.on('request', (pieceIndex, offset, length, callback) => { debug('request pieceIndex=%d offset=%d length=%d', pieceIndex, offset, length) this.httpRequest(pieceIndex, offset, length, (err, data) => { - // TODO: timeout - if (err) { // Cancel all in progress requests for this piece this.lt_donthave.donthave(pieceIndex) - this.bitfield.set(pieceIndex, false) - // TODO: delay before re-advertising - this.have(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) @@ -133,7 +138,8 @@ 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) { -- cgit v1.2.3