From 1264106b627fad90faedddb4daec27feb52c138d Mon Sep 17 00:00:00 2001 From: Brad Marsden Date: Sat, 4 Jan 2025 15:58:59 +0000 Subject: [PATCH] feat: add maxPieceLength option (#267) * feat: add maxPieceLength option to address #266 * fix: update default maxPieceLength to be 4 MiB, rather than Infinity. --- README.md | 1 + index.js | 7 ++++++- test/basic.js | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 32a3739f..32790561 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ Or, an **array of `string`, `File`, `Buffer`, or `stream.Readable` objects**. filterJunkFiles: Boolean, // remove hidden and other junk files? (default = true) private: Boolean, // is this a private .torrent? (default = false) pieceLength: Number, // force a custom piece length (number of bytes) + maxPieceLength: Number, // force a maximum piece length for auto piece length selection, does not affect pieceLength option (default = 4 MiB) announceList: [[String]], // custom trackers (array of arrays of strings) (see [bep12](http://www.bittorrent.org/beps/bep_0012.html)) urlList: [String], // web seed urls (see [bep19](http://www.bittorrent.org/beps/bep_0019.html)) info: Object, // add non-standard info dict entries, e.g. info.source, a convention for cross-seeding diff --git a/index.js b/index.js index 1f60e210..bdec153f 100644 --- a/index.js +++ b/index.js @@ -34,6 +34,7 @@ const announceList = [ * @param {string=} opts.createdBy * @param {boolean|number=} opts.private * @param {number=} opts.pieceLength + * @param {number=} opts.maxPieceLength * @param {Array.>=} opts.announceList * @param {Array.=} opts.urlList * @param {Object=} opts.info @@ -151,6 +152,10 @@ function _parseInput (input, opts, cb) { opts.name = `Unnamed Torrent ${Date.now()}` } + if (!opts.maxPieceLength) { + opts.maxPieceLength = 4 * 1024 * 1024 + } + const numPaths = input.reduce((sum, item) => sum + Number(typeof item === 'string'), 0) let isSingleFileTorrent = (input.length === 1) @@ -300,7 +305,7 @@ function onFiles (files, opts, cb) { if (opts.urlList !== undefined) torrent['url-list'] = opts.urlList const estimatedTorrentLength = files.reduce(sumLength, 0) - const pieceLength = opts.pieceLength || calcPieceLength(estimatedTorrentLength) + const pieceLength = opts.pieceLength || Math.min(calcPieceLength(estimatedTorrentLength), opts.maxPieceLength) torrent.info['piece length'] = pieceLength getPieceList( diff --git a/test/basic.js b/test/basic.js index ca2306bc..4e9df238 100644 --- a/test/basic.js +++ b/test/basic.js @@ -205,3 +205,57 @@ test('implicit torrent name from file names with slashes in them', t => { t.equal(parsedTorrent.files[1].path, path.join('My Cool Folder', 'My Cool File 2')) }) }) + +test('verify torrent length with maxPieceLength set', t => { + t.plan(8) + + const buf1 = Buffer.from('buf1') + buf1.name = 'My Cool Folder/My Cool File 1' + + const buf2 = Buffer.from('buf2') + buf2.name = 'My Cool Folder/My Cool File 2' + + createTorrent([buf1, buf2], { maxPieceLength: 10 }, async (err, torrent) => { + t.error(err) + const parsedTorrent = await parseTorrent(torrent) + + t.equal(parsedTorrent.name, 'My Cool Folder') + + t.equal(parsedTorrent.files.length, 2) + + t.equal(parsedTorrent.files[0].name, 'My Cool File 1') + t.equal(parsedTorrent.files[0].path, path.join('My Cool Folder', 'My Cool File 1')) + + t.equal(parsedTorrent.files[1].name, 'My Cool File 2') + t.equal(parsedTorrent.files[1].path, path.join('My Cool Folder', 'My Cool File 2')) + + t.equal(parsedTorrent.pieceLength, 10) + }) +}) + +test('verify maxPieceLength is ignored when pieceLength is manually set', t => { + t.plan(8) + + const buf1 = Buffer.from('buf1') + buf1.name = 'My Cool Folder/My Cool File 1' + + const buf2 = Buffer.from('buf2') + buf2.name = 'My Cool Folder/My Cool File 2' + + createTorrent([buf1, buf2], { pieceLength: 1024, maxPieceLength: 10 }, async (err, torrent) => { + t.error(err) + const parsedTorrent = await parseTorrent(torrent) + + t.equal(parsedTorrent.name, 'My Cool Folder') + + t.equal(parsedTorrent.files.length, 2) + + t.equal(parsedTorrent.files[0].name, 'My Cool File 1') + t.equal(parsedTorrent.files[0].path, path.join('My Cool Folder', 'My Cool File 1')) + + t.equal(parsedTorrent.files[1].name, 'My Cool File 2') + t.equal(parsedTorrent.files[1].path, path.join('My Cool Folder', 'My Cool File 2')) + + t.equal(parsedTorrent.pieceLength, 1024) + }) +})