From 03b7ecc11d7de8ced079c95124950b3df4efaf05 Mon Sep 17 00:00:00 2001 From: Book Moons <35854232+bookmoons@users.noreply.github.com> Date: Sat, 14 Jul 2018 11:01:07 -0400 Subject: [PATCH 1/9] Persist DHT nodes Persists DHT nodes to disk every 15 minutes. Loads persisted nodes on construction. Enabled by default. Default save file is dht.json, under crossplatform app data folder provided by app-data-folder. Adds option dhtState to configure: * false disables * true enables with default path * String specifies path to custom save file --- docs/api.md | 13 ++++--- index.js | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++- package.json | 2 + 3 files changed, 110 insertions(+), 7 deletions(-) diff --git a/docs/api.md b/docs/api.md index 52d11252..f8a3a3eb 100644 --- a/docs/api.md +++ b/docs/api.md @@ -53,12 +53,13 @@ If `opts` is specified, then the default options (shown below) will be overridde ```js { - maxConns: Number, // Max number of connections per torrent (default=55) - nodeId: String|Buffer, // DHT protocol node ID (default=randomly generated) - peerId: String|Buffer, // Wire protocol peer ID (default=randomly generated) - tracker: Boolean|Object, // Enable trackers (default=true), or options object for Tracker - dht: Boolean|Object, // Enable DHT (default=true), or options object for DHT - webSeeds: Boolean // Enable BEP19 web seeds (default=true) + maxConns: Number, // Max number of connections per torrent (default=55) + nodeId: String|Buffer, // DHT protocol node ID (default=randomly generated) + peerId: String|Buffer, // Wire protocol peer ID (default=randomly generated) + tracker: Boolean|Object, // Enable trackers (default=true), or options object for Tracker + dht: Boolean|Object, // Enable DHT (default=true), or options object for DHT + dhtState: Boolean|String, // Persist DHT nodes (default=true), or save file path + webSeeds: Boolean // Enable BEP19 web seeds (default=true) } ``` diff --git a/index.js b/index.js index b90fc87d..48b4c81e 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ module.exports = WebTorrent +var appDataFolder = require('app-data-folder') var Buffer = require('safe-buffer').Buffer var concat = require('simple-concat') var createTorrent = require('create-torrent') @@ -9,8 +10,10 @@ var debug = require('debug')('webtorrent') var DHT = require('bittorrent-dht/client') // browser exclude var EventEmitter = require('events').EventEmitter var extend = require('xtend') +var fs = require('fs') var inherits = require('inherits') var loadIPSet = require('load-ip-set') // browser exclude +var mkdirp = require('mkdirp') var parallel = require('run-parallel') var parseTorrent = require('parse-torrent') var path = require('path') @@ -78,6 +81,9 @@ function WebTorrent (opts) { } self.nodeIdBuffer = Buffer.from(self.nodeId, 'hex') + // Default opts.dhtState to true + if (!('dhtState' in opts)) opts.dhtState = true + self._debugId = self.peerId.toString('hex').substring(0, 7) self.destroyed = false @@ -122,9 +128,102 @@ function WebTorrent (opts) { self._downloadSpeed = speedometer() self._uploadSpeed = speedometer() + // DHT state save location + var dhtSaveFile + + var savingDhtState = false + function saveDhtState () { + if (savingDhtState) return + if (!self.dht) return // Quell after destroy + savingDhtState = true + var dhtState = self.dht.toJSON() + var dhtStateJson = JSON.stringify(dhtState) + mkdirp( + path.dirname(dhtSaveFile), + function handleDhtSaveDirCreated (err) { + if (err) { + savingDhtState = false + return + } + fs.writeFile( + dhtSaveFile, + dhtStateJson, + function handleDhtStateWritten () { + savingDhtState = false + } + ) + } + ) + } + + function readDhtState (file) { + try { + return fs.readFileSync(file) + } catch (e) { + switch (e.code) { + case 'EACCES': + case 'EISDIR': + case 'ENOENT': + case 'EPERM': + return null + default: + throw e + } + } + } + + function parseDhtState (dhtStateJson) { + try { + return JSON.parse(dhtStateJson) + } catch (e) { + if (e instanceof SyntaxError) return null + else throw e + } + } + + function loadDhtState (file) { + var dhtStateJson = readDhtState(file) + if (!dhtStateJson) return null + var dhtState = parseDhtState(dhtStateJson) + if (!dhtState) return null + return dhtState + } + + function loadDhtNodes (file) { + var dhtState = loadDhtState(file) + if (!dhtState) return null + if (!('nodes' in dhtState)) return null + var nodes = dhtState.nodes + if (!Array.isArray(nodes)) return null + if (nodes.length === 0) return null // Don't load an empty nodes list + return nodes + } + if (opts.dht !== false && typeof DHT === 'function' /* browser exclude */) { + var dhtOpts = extend({ nodeId: self.nodeId }, opts.dht) + + if (opts.dhtState) { + // Construct state save location + dhtSaveFile = + opts.dhtState === true + ? path.join(appDataFolder('webtorrent'), 'dht.json') + : opts.dhtState + + if (!('bootstrap' in dhtOpts)) { + // Load persisted state + var nodes = loadDhtNodes(dhtSaveFile) + if (nodes) dhtOpts.bootstrap = nodes + } + } + // use a single DHT instance for all torrents, so the routing table can be reused - self.dht = new DHT(extend({ nodeId: self.nodeId }, opts.dht)) + self.dht = new DHT(dhtOpts) + + if (opts.dhtState) { + // Persist state periodically + var saveInterval = 15 * 60 * 1000 // 15 minutes + self.saveDhtStateTimer = setInterval(saveDhtState, saveInterval) + } self.dht.once('error', function (err) { self._destroy(err) @@ -428,6 +527,7 @@ WebTorrent.prototype._destroy = function (err, cb) { if (self.dht) { tasks.push(function (cb) { + clearInterval(self.saveDhtStateTimer) self.dht.destroy(cb) }) } diff --git a/package.json b/package.json index e514ac45..99b0244e 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ }, "dependencies": { "addr-to-ip-port": "^1.4.2", + "app-data-folder": "^1.0.0", "bitfield": "^2.0.0", "bittorrent-dht": "^8.0.0", "bittorrent-protocol": "^2.1.5", @@ -40,6 +41,7 @@ "load-ip-set": "^1.2.7", "memory-chunk-store": "^1.2.0", "mime": "^2.2.0", + "mkdirp": "^0.5.1", "multistream": "^2.0.5", "package-json-versionify": "^1.0.2", "parse-numeric-range": "^0.0.2", From a7ed3a26867806759cf2b702cc6be7519a19d9d4 Mon Sep 17 00:00:00 2001 From: Book Moons <35854232+bookmoons@users.noreply.github.com> Date: Sun, 29 Jul 2018 23:29:38 -0400 Subject: [PATCH 2/9] Move DHT persistence logic into lib/ module Increases cleanliness of index.js. --- index.js | 96 ++++++++++------------------------------------- lib/dhtpersist.js | 78 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 76 deletions(-) create mode 100644 lib/dhtpersist.js diff --git a/index.js b/index.js index 48b4c81e..cbc016a1 100644 --- a/index.js +++ b/index.js @@ -10,10 +10,8 @@ var debug = require('debug')('webtorrent') var DHT = require('bittorrent-dht/client') // browser exclude var EventEmitter = require('events').EventEmitter var extend = require('xtend') -var fs = require('fs') var inherits = require('inherits') var loadIPSet = require('load-ip-set') // browser exclude -var mkdirp = require('mkdirp') var parallel = require('run-parallel') var parseTorrent = require('parse-torrent') var path = require('path') @@ -22,6 +20,7 @@ var randombytes = require('randombytes') var speedometer = require('speedometer') var zeroFill = require('zero-fill') +var dhtPersist = require('./lib/dhtpersist') // browser exclude var TCPPool = require('./lib/tcp-pool') // browser exclude var Torrent = require('./lib/torrent') @@ -128,90 +127,19 @@ function WebTorrent (opts) { self._downloadSpeed = speedometer() self._uploadSpeed = speedometer() - // DHT state save location - var dhtSaveFile - - var savingDhtState = false - function saveDhtState () { - if (savingDhtState) return - if (!self.dht) return // Quell after destroy - savingDhtState = true - var dhtState = self.dht.toJSON() - var dhtStateJson = JSON.stringify(dhtState) - mkdirp( - path.dirname(dhtSaveFile), - function handleDhtSaveDirCreated (err) { - if (err) { - savingDhtState = false - return - } - fs.writeFile( - dhtSaveFile, - dhtStateJson, - function handleDhtStateWritten () { - savingDhtState = false - } - ) - } - ) - } - - function readDhtState (file) { - try { - return fs.readFileSync(file) - } catch (e) { - switch (e.code) { - case 'EACCES': - case 'EISDIR': - case 'ENOENT': - case 'EPERM': - return null - default: - throw e - } - } - } - - function parseDhtState (dhtStateJson) { - try { - return JSON.parse(dhtStateJson) - } catch (e) { - if (e instanceof SyntaxError) return null - else throw e - } - } - - function loadDhtState (file) { - var dhtStateJson = readDhtState(file) - if (!dhtStateJson) return null - var dhtState = parseDhtState(dhtStateJson) - if (!dhtState) return null - return dhtState - } - - function loadDhtNodes (file) { - var dhtState = loadDhtState(file) - if (!dhtState) return null - if (!('nodes' in dhtState)) return null - var nodes = dhtState.nodes - if (!Array.isArray(nodes)) return null - if (nodes.length === 0) return null // Don't load an empty nodes list - return nodes - } - if (opts.dht !== false && typeof DHT === 'function' /* browser exclude */) { var dhtOpts = extend({ nodeId: self.nodeId }, opts.dht) if (opts.dhtState) { // Construct state save location - dhtSaveFile = + self.dhtSaveFile = opts.dhtState === true ? path.join(appDataFolder('webtorrent'), 'dht.json') : opts.dhtState if (!('bootstrap' in dhtOpts)) { // Load persisted state - var nodes = loadDhtNodes(dhtSaveFile) + var nodes = dhtPersist.loadNodes(self.dhtSaveFile) if (nodes) dhtOpts.bootstrap = nodes } } @@ -222,7 +150,9 @@ function WebTorrent (opts) { if (opts.dhtState) { // Persist state periodically var saveInterval = 15 * 60 * 1000 // 15 minutes - self.saveDhtStateTimer = setInterval(saveDhtState, saveInterval) + self.saveDhtStateTimer = setInterval(function saveDhtState () { + dhtPersist.save(self.dht, self.dhtSaveFile) + }, saveInterval) } self.dht.once('error', function (err) { @@ -499,6 +429,20 @@ WebTorrent.prototype.address = function () { : { address: '0.0.0.0', family: 'IPv4', port: 0 } } +/** + * Persist DHT state to disk. + * No effect if DHT is not loaded. + */ +WebTorrent.prototype.saveDhtState = function (cb) { + if ( + this.dht !== false && + this.dhtSaveFile && + typeof DHT === 'function' /* browser exclude */ + ) { + dhtPersist.save(this.dht, this.dhtSaveFile, cb) + } +} + /** * Destroy the client, including all torrents and connections to peers. * @param {function} cb diff --git a/lib/dhtpersist.js b/lib/dhtpersist.js new file mode 100644 index 00000000..383f00d7 --- /dev/null +++ b/lib/dhtpersist.js @@ -0,0 +1,78 @@ +var fs = require('fs') +var mkdirp = require('mkdirp') +var path = require('path') + +var savingDhtState = false +function saveDhtState (dht, file, cb) { + if (savingDhtState) return + if (!dht) return // Quell after destroy + savingDhtState = true + var dhtState = dht.toJSON() + var dhtStateJson = JSON.stringify(dhtState) + mkdirp( + path.dirname(file), + function handleDhtSaveDirCreated (err) { + if (err) { + savingDhtState = false + if (cb) cb(err) + return + } + fs.writeFile( + file, + dhtStateJson, + function handleDhtStateWritten () { + savingDhtState = false + if (cb) cb(null) + } + ) + } + ) +} + +function readDhtState (file) { + try { + return fs.readFileSync(file) + } catch (e) { + switch (e.code) { + case 'EACCES': + case 'EISDIR': + case 'ENOENT': + case 'EPERM': + return null + default: + throw e + } + } +} + +function parseDhtState (dhtStateJson) { + try { + return JSON.parse(dhtStateJson) + } catch (e) { + if (e instanceof SyntaxError) return null + else throw e + } +} + +function loadDhtState (file) { + var dhtStateJson = readDhtState(file) + if (!dhtStateJson) return null + var dhtState = parseDhtState(dhtStateJson) + if (!dhtState) return null + return dhtState +} + +function loadDhtNodes (file) { + var dhtState = loadDhtState(file) + if (!dhtState) return null + if (!('nodes' in dhtState)) return null + var nodes = dhtState.nodes + if (!Array.isArray(nodes)) return null + if (nodes.length === 0) return null // Don't load an empty nodes list + return nodes +} + +module.exports = { + save: saveDhtState, + loadNodes: loadDhtNodes +} From c2f594385e7c0f27a4a373ebdd1adf632819cb58 Mon Sep 17 00:00:00 2001 From: Book Moons <35854232+bookmoons@users.noreply.github.com> Date: Sun, 29 Jul 2018 23:33:43 -0400 Subject: [PATCH 3/9] Add save DHT state test --- package.json | 1 + test/node/persist-dht-nodes.js | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 test/node/persist-dht-nodes.js diff --git a/package.json b/package.json index 99b0244e..81c5ed92 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "serve-static": "^1.11.1", "standard": "*", "tape": "^4.6.0", + "tmp": "0.0.33", "webtorrent-fixtures": "^1.5.0" }, "engines": { diff --git a/test/node/persist-dht-nodes.js b/test/node/persist-dht-nodes.js new file mode 100644 index 00000000..89757065 --- /dev/null +++ b/test/node/persist-dht-nodes.js @@ -0,0 +1,41 @@ +var test = require('tape') +var tmp = require('tmp') +var fs = require('fs') +var DHT = require('bittorrent-dht/server') +var WebTorrent = require('../../') + +var localHost = '127.0.0.1' +var port = 9999 + +test('Save DHT state', function (t) { + t.plan(4) + var saveFile = tmp.tmpNameSync() + var dhtServer = new DHT({ bootstrap: false }) + dhtServer.on('error', function (err) { t.fail(err) }) + dhtServer.on('warning', function (err) { t.fail(err) }) + dhtServer.listen(port, function handleServerListening () { + var client = new WebTorrent({ + dht: { bootstrap: false }, + dhtState: saveFile + }) + client.on('error', function (err) { t.fail(err) }) + client.on('warning', function (err) { t.fail(err) }) + client.dht.addNode({ host: localHost, port: port }) + client.dht.on('node', function handleNodeAdded () { + client.saveDhtState(function handleDhtStateSaved () { + var dhtStateJson = fs.readFileSync(saveFile) + var dhtState = JSON.parse(dhtStateJson) + var nodes = dhtState.nodes + var node = nodes[0] + t.equal(node.host, localHost) + t.equal(node.port, port) + client.destroy(function handleClientDestroyed (err) { + t.error(err, 'client destroyed') + }) + dhtServer.destroy(function handleDhtServerDestroyed (err) { + t.error(err, 'dht server destroyed') + }) + }) + }) + }) +}) From 2852b671575a3bd76bb4e81d07dd5de9e7e0ba7f Mon Sep 17 00:00:00 2001 From: Book Moons <35854232+bookmoons@users.noreply.github.com> Date: Mon, 30 Jul 2018 12:36:34 -0400 Subject: [PATCH 4/9] Distinguish addresses in DHT persistence test Uses loopback for the test DHT server, a local address provided by the network-address module for the client. This is the pattern used in other tests. --- test/node/persist-dht-nodes.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/node/persist-dht-nodes.js b/test/node/persist-dht-nodes.js index 89757065..e84fccbc 100644 --- a/test/node/persist-dht-nodes.js +++ b/test/node/persist-dht-nodes.js @@ -1,13 +1,15 @@ var test = require('tape') var tmp = require('tmp') var fs = require('fs') +var networkAddress = require('network-address') var DHT = require('bittorrent-dht/server') var WebTorrent = require('../../') -var localHost = '127.0.0.1' +var loopback = '127.0.0.1' +var localAddress = networkAddress.ipv4() var port = 9999 -test('Save DHT state', function (t) { +test.only('Save DHT state', function (t) { t.plan(4) var saveFile = tmp.tmpNameSync() var dhtServer = new DHT({ bootstrap: false }) @@ -15,19 +17,19 @@ test('Save DHT state', function (t) { dhtServer.on('warning', function (err) { t.fail(err) }) dhtServer.listen(port, function handleServerListening () { var client = new WebTorrent({ - dht: { bootstrap: false }, + dht: { bootstrap: false, host: localAddress }, dhtState: saveFile }) client.on('error', function (err) { t.fail(err) }) client.on('warning', function (err) { t.fail(err) }) - client.dht.addNode({ host: localHost, port: port }) + client.dht.addNode({ host: loopback, port: port }) client.dht.on('node', function handleNodeAdded () { client.saveDhtState(function handleDhtStateSaved () { var dhtStateJson = fs.readFileSync(saveFile) var dhtState = JSON.parse(dhtStateJson) var nodes = dhtState.nodes var node = nodes[0] - t.equal(node.host, localHost) + t.equal(node.host, loopback) t.equal(node.port, port) client.destroy(function handleClientDestroyed (err) { t.error(err, 'client destroyed') From ff755bc932d8d3abc585e03b4d303697cf8598d7 Mon Sep 17 00:00:00 2001 From: Book Moons <35854232+bookmoons@users.noreply.github.com> Date: Mon, 30 Jul 2018 13:12:57 -0400 Subject: [PATCH 5/9] Correct DHT state loading Saved node data and the bootstrap list use different formats. Converts to the bootstrap format. --- index.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index cbc016a1..341ded78 100644 --- a/index.js +++ b/index.js @@ -140,7 +140,14 @@ function WebTorrent (opts) { if (!('bootstrap' in dhtOpts)) { // Load persisted state var nodes = dhtPersist.loadNodes(self.dhtSaveFile) - if (nodes) dhtOpts.bootstrap = nodes + if (nodes) { + var bootstrap = [] + for (var node of nodes) { + var nodeString = node.host + ':' + node.port + bootstrap.push(nodeString) + } + dhtOpts.bootstrap = bootstrap + } } } From d6e090f488eb771850f6d5739c3141af96da0141 Mon Sep 17 00:00:00 2001 From: Book Moons <35854232+bookmoons@users.noreply.github.com> Date: Mon, 30 Jul 2018 13:15:39 -0400 Subject: [PATCH 6/9] Allow DHT state loading when bootstrap disabled Prior logic disabled DHT state load with any bootstrap value, including a false to disable. Changes to allowing DHT state load if bootstrap is explicitly disabled with a falsy value. --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 341ded78..36c7c0d3 100644 --- a/index.js +++ b/index.js @@ -137,7 +137,7 @@ function WebTorrent (opts) { ? path.join(appDataFolder('webtorrent'), 'dht.json') : opts.dhtState - if (!('bootstrap' in dhtOpts)) { + if (!dhtOpts.bootstrap) { // Load persisted state var nodes = dhtPersist.loadNodes(self.dhtSaveFile) if (nodes) { From 2a3e7ee02485d163d7e4366bd00c86104945b992 Mon Sep 17 00:00:00 2001 From: Book Moons <35854232+bookmoons@users.noreply.github.com> Date: Mon, 30 Jul 2018 13:21:07 -0400 Subject: [PATCH 7/9] Add load DHT state test --- test/node/persist-dht-nodes.js | 39 +++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/test/node/persist-dht-nodes.js b/test/node/persist-dht-nodes.js index e84fccbc..dcedbcde 100644 --- a/test/node/persist-dht-nodes.js +++ b/test/node/persist-dht-nodes.js @@ -9,7 +9,7 @@ var loopback = '127.0.0.1' var localAddress = networkAddress.ipv4() var port = 9999 -test.only('Save DHT state', function (t) { +test('Save DHT state', function (t) { t.plan(4) var saveFile = tmp.tmpNameSync() var dhtServer = new DHT({ bootstrap: false }) @@ -41,3 +41,40 @@ test.only('Save DHT state', function (t) { }) }) }) + +test('Load DHT state', function (t) { + t.plan(4) + var saveFile = tmp.tmpNameSync() + var node = { + host: loopback, + port: port + } + var nodes = [ node ] + var dhtState = { nodes: nodes, values: {} } + var dhtStateJson = JSON.stringify(dhtState) + fs.writeFileSync(saveFile, dhtStateJson) + var dhtServer = new DHT({ bootstrap: false }) + dhtServer.on('error', function (err) { t.fail(err) }) + dhtServer.on('warning', function (err) { t.fail(err) }) + dhtServer.listen(port, function handleServerListening () { + var client = new WebTorrent({ + dht: { host: localAddress }, + dhtState: saveFile + }) + client.on('error', function (err) { t.fail(err) }) + client.on('warning', function (err) { t.fail(err) }) + client.dht.on('ready', function handleReady () { + var dhtState = client.dht.toJSON() + var nodes = dhtState.nodes + var node = nodes[0] + t.equal(node.host, loopback) + t.equal(node.port, port) + client.destroy(function handleClientDestroyed (err) { + t.error(err, 'client destroyed') + }) + dhtServer.destroy(function handleDhtServerDestroyed (err) { + t.error(err, 'dht server destroyed') + }) + }) + }) +}) From 02879a0f751209cc480d062a271687c80baee5c9 Mon Sep 17 00:00:00 2001 From: Book Moons <35854232+bookmoons@users.noreply.github.com> Date: Sun, 5 Aug 2018 22:38:26 -0400 Subject: [PATCH 8/9] Exclude dhtpersist on browser --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 81c5ed92..2005ad07 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "url": "https://webtorrent.io" }, "browser": { + "./lib/dhtpersist.js": false, "./lib/server.js": false, "./lib/tcp-pool.js": false, "bittorrent-dht/client": false, From 7f26a8c6e13095232aa80bef37cb03bc3fe4234b Mon Sep 17 00:00:00 2001 From: Book Moons <35854232+bookmoons@users.noreply.github.com> Date: Sun, 5 Aug 2018 22:57:21 -0400 Subject: [PATCH 9/9] Split DHT persistence options Splits from single option dhtState into 2 options: * persistDht - Boolean. Flag to enable. * persistDhtPath - String. Optional custom path for save file. --- docs/api.md | 3 ++- index.js | 13 ++++++------- test/node/persist-dht-nodes.js | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/api.md b/docs/api.md index f8a3a3eb..dc47c41e 100644 --- a/docs/api.md +++ b/docs/api.md @@ -58,7 +58,8 @@ If `opts` is specified, then the default options (shown below) will be overridde peerId: String|Buffer, // Wire protocol peer ID (default=randomly generated) tracker: Boolean|Object, // Enable trackers (default=true), or options object for Tracker dht: Boolean|Object, // Enable DHT (default=true), or options object for DHT - dhtState: Boolean|String, // Persist DHT nodes (default=true), or save file path + persistDht: Boolean, // Persist DHT nodes (default=true) + persistDhtPath: String, // DHT persist save file (default=dht.json under OS appdata dir) webSeeds: Boolean // Enable BEP19 web seeds (default=true) } ``` diff --git a/index.js b/index.js index 36c7c0d3..7cddcdb6 100644 --- a/index.js +++ b/index.js @@ -80,8 +80,8 @@ function WebTorrent (opts) { } self.nodeIdBuffer = Buffer.from(self.nodeId, 'hex') - // Default opts.dhtState to true - if (!('dhtState' in opts)) opts.dhtState = true + // Default DHT persistence flag + if (!('persistDht' in opts)) opts.persistDht = true self._debugId = self.peerId.toString('hex').substring(0, 7) @@ -130,12 +130,11 @@ function WebTorrent (opts) { if (opts.dht !== false && typeof DHT === 'function' /* browser exclude */) { var dhtOpts = extend({ nodeId: self.nodeId }, opts.dht) - if (opts.dhtState) { + if (opts.persistDht) { // Construct state save location self.dhtSaveFile = - opts.dhtState === true - ? path.join(appDataFolder('webtorrent'), 'dht.json') - : opts.dhtState + opts.persistDhtPath || + path.join(appDataFolder('webtorrent'), 'dht.json') if (!dhtOpts.bootstrap) { // Load persisted state @@ -154,7 +153,7 @@ function WebTorrent (opts) { // use a single DHT instance for all torrents, so the routing table can be reused self.dht = new DHT(dhtOpts) - if (opts.dhtState) { + if (opts.persistDht) { // Persist state periodically var saveInterval = 15 * 60 * 1000 // 15 minutes self.saveDhtStateTimer = setInterval(function saveDhtState () { diff --git a/test/node/persist-dht-nodes.js b/test/node/persist-dht-nodes.js index dcedbcde..5314477e 100644 --- a/test/node/persist-dht-nodes.js +++ b/test/node/persist-dht-nodes.js @@ -18,7 +18,7 @@ test('Save DHT state', function (t) { dhtServer.listen(port, function handleServerListening () { var client = new WebTorrent({ dht: { bootstrap: false, host: localAddress }, - dhtState: saveFile + persistDhtPath: saveFile }) client.on('error', function (err) { t.fail(err) }) client.on('warning', function (err) { t.fail(err) }) @@ -59,7 +59,7 @@ test('Load DHT state', function (t) { dhtServer.listen(port, function handleServerListening () { var client = new WebTorrent({ dht: { host: localAddress }, - dhtState: saveFile + persistDhtPath: saveFile }) client.on('error', function (err) { t.fail(err) }) client.on('warning', function (err) { t.fail(err) })