diff --git a/docs/API.md b/docs/API.md index ad770b1..1ab8129 100644 --- a/docs/API.md +++ b/docs/API.md @@ -18,6 +18,7 @@ The following can be passed as the second `opts` argument to `Bugout(identifier, * `wt` - a [WebTorrent instance](https://webtorrent.io/docs) to re-use. Pass this in if you're making connections to multiple Bugout channels. * `wtOpts` - options that will be passed when [creating the WebTorrent object](https://github.com/webtorrent/webtorrent/blob/master/docs/api.md#client--new-webtorrentopts). + * `torrent` - a torrent to extend with Bugout RPC / gossip extension. If provided a new torrent will not be created. * `torrentOpts` - options that will be passed to the [WebTorrent seed method](https://github.com/webtorrent/webtorrent/blob/master/docs/api.md#clientseedinput-opts-function-onseed-torrent-). * `seed` - base58 encoded seed used to generate an [nacl signing key pair](https://github.com/dchest/tweetnacl-js#signatures). * `keyPair` - pass [nacl signing key pair](https://github.com/dchest/tweetnacl-js#signatures) directly rather than a seed. diff --git a/index.js b/index.js index 050f150..6f045cc 100644 --- a/index.js +++ b/index.js @@ -36,7 +36,7 @@ function Bugout(identifier, opts) { } this.announce = opts.announce || ["wss://hub.bugout.link", "wss://tracker.openwebtorrent.com", "wss://tracker.btorrent.xyz"]; - this.wt = opts.wt || new WebTorrent(Object.assign({tracker: trackeropts}, opts["wtOpts"] || {})); + this.wt = opts.wt; this.nacl = nacl; if (opts["seed"]) { @@ -75,19 +75,29 @@ function Bugout(identifier, opts) { var blob = new Buffer.from(this.identifier); blob.name = this.identifier; } - var torrent = this.wt.seed(blob, Object.assign({"name": this.identifier, "announce": this.announce}, opts["torrentOpts"] || {}), partial(function(bugout, torrent) { - debug("torrent", bugout.identifier, torrent); - bugout.emit("torrent", bugout.identifier, torrent); - if (torrent.discovery.tracker) { - torrent.discovery.tracker.on("update", function(update) { bugout.emit("tracker", bugout.identifier, update); }); + + // Caller may already be seeding a torrent... + if (opts.torrent) { + this.torrent = opts.torrent; + this.torrentCreated = false; + // 'ready' may have already fired. + if (this.torrent.ready) { + this._onTorrent(); + } else { + this.torrent.on('ready', this._onTorrent.bind(this)); } - torrent.discovery.on("trackerAnnounce", function() { - bugout.emit("announce", bugout.identifier); - bugout.connections(); + // Could be existing wires... + this.torrent.wires.forEach((wire) => { + attach(this, this.identifier, wire, wire.addr); }); - }, this)); - torrent.on("wire", partial(attach, this, this.identifier)); - this.torrent = torrent; + } else { + this.wt = this.wt || new WebTorrent(Object.assign({tracker: trackeropts}, opts["wtOpts"] || {})); + this.torrent = this.wt.seed(blob, Object.assign({"name": this.identifier, "announce": this.announce}, opts["torrentOpts"] || {}), partial(function(bugout, torrent) { + bugout._onTorrent(); + }, this)); + this.torrentCreated = true; + } + this.torrent.on("wire", partial(attach, this, this.identifier)); if (opts.heartbeat) { this.heartbeat(opts.heartbeat); @@ -96,6 +106,20 @@ function Bugout(identifier, opts) { Bugout.prototype.WebTorrent = WebTorrent; +Bugout.prototype._onTorrent = function() { + debug("torrent", this.identifier, this.torrent); + this.emit("torrent", this.identifier, this.torrent); + if (this.torrent.discovery.tracker) { + this.torrent.discovery.tracker.on("update", partial(function(bugout, update) { + bugout.emit("tracker", bugout.identifier, update); + }, this)); + } + this.torrent.discovery.on("trackerAnnounce", partial(function(bugout) { + bugout.emit("announce", bugout.identifier); + bugout.connections(); + }, this)); +} + Bugout.encodeseed = Bugout.prototype.encodeseed = function(material) { return bs58check.encode(Buffer.concat([Buffer.from(SEEDPREFIX, "hex"), Buffer.from(material)])); } @@ -130,7 +154,10 @@ Bugout.prototype.destroy = function(cb) { clearInterval(this.heartbeattimer); var packet = makePacket(this, {"y": "x"}); sendRaw(this, packet); - this.wt.remove(this.torrent, cb); + // If caller provided the torrent, no need to clean it up. + if (this.wt && this.torrentCreated) { + this.wt.remove(this.torrent, cb); + } } Bugout.prototype.close = Bugout.prototype.destroy; diff --git a/test.js b/test.js index cf1f27c..be3c850 100644 --- a/test.js +++ b/test.js @@ -21,7 +21,7 @@ test.onFinish(function() { }); test('Instantiation', function (t) { - t.plan(10); + t.plan(12); var b1 = new Bugout({seed: "BohNtZ24TrgMwZTLx9VDKtcZARNVuCt5tnecAAxYtTBC8pC61uGN", wt: wtest}); t.equal(b1.identifier, "bYSkTy24xXJj6dWe79ZAQXKJZrn2n983SQ", "server identifier"); @@ -49,6 +49,11 @@ test('Instantiation', function (t) { console.log(b4.torrent.infoHash); t.equal(b4.torrent.infoHash, "5486696a87e91c6c7fcfc6279c9b08709c7aa61f", "client infoHash"); }); + + var b5 = new Bugout({torrent: b4.torrent}); + t.equal(b5.torrentCreated, false); + b5.destroy(); + t.equal(b4.torrent, b5.torrent); }); test("Connectivity events", function(t) {