diff --git a/README.md b/README.md index 56b2676a..0c4cf68b 100644 --- a/README.md +++ b/README.md @@ -266,7 +266,8 @@ If `opts` is specified, then the default options (shown below) will be overridde rtcConfig: Object, // RTCPeerConnection configuration object (default=STUN only) storage: Function, // custom storage engine, or `false` to use in-memory engine tracker: Boolean, // Whether or not to enable trackers (default=true) - wrtc: {} // custom webrtc implementation (in node, specify the [wrtc](https://www.npmjs.com/package/wrtc) package) + wrtc: {}, // custom webrtc implementation (in node, specify the [wrtc](https://www.npmjs.com/package/wrtc) package) + onWire: Function // function to be called on each new wire. Use this to specify [custom bittorrent extensions](https://www.npmjs.com/package/bittorrent-protocol#extension-api) } ``` diff --git a/index.js b/index.js index 62026f38..b9400b91 100644 --- a/index.js +++ b/index.js @@ -43,6 +43,7 @@ function WebTorrent (opts) { self.destroyed = false self.torrentPort = opts.torrentPort || 0 self.tracker = opts.tracker !== undefined ? opts.tracker : true + self.onWire = opts.onWire self._rtcConfig = opts.rtcConfig self._wrtc = opts.wrtc || global.WRTC // to support `webtorrent-hybrid` package @@ -156,6 +157,7 @@ WebTorrent.prototype.download = function (torrentId, opts, ontorrent) { } if (!opts) opts = {} if (!opts.storage) opts.storage = self.storage + if (!opts.onWire) opts.onWire = self.onWire opts.client = self var torrent = self.get(torrentId) diff --git a/lib/torrent.js b/lib/torrent.js index 4d7e65ff..a35342a7 100644 --- a/lib/torrent.js +++ b/lib/torrent.js @@ -501,6 +501,11 @@ Torrent.prototype._onWire = function (wire, addr) { }) } + // trigger opts.onWire to allow user-defined extensions + if (typeof this.opts.onWire === 'function') { + this.opts.onWire.call(this, wire) + } + // Send KEEP-ALIVE (every 60s) so peers will not disconnect the wire wire.setKeepAlive(true) diff --git a/test/extensions.js b/test/extensions.js new file mode 100644 index 00000000..f5537439 --- /dev/null +++ b/test/extensions.js @@ -0,0 +1,54 @@ +var fs = require('fs') +var parseTorrent = require('parse-torrent') +var test = require('tape') +var WebTorrent = require('../') + +var leaves = fs.readFileSync(__dirname + '/torrents/leaves.torrent') +var leavesTorrent = parseTorrent(leaves) + +test('onWire option', {timeout: 500}, function (t) { + t.plan(6) + var extendedHandshakes = 0 + + function Extension (wire) { + wire.extendedHandshake.test = 'Hello, World!' + } + + Extension.prototype.name = 'wt_test' + Extension.prototype.onExtendedHandshake = function (handshake) { + t.equal(handshake.test.toString(), 'Hello, World!', 'handshake.test === Hello, World!') + extendedHandshakes++ + if (extendedHandshakes === 2) { + client1.destroy(function () { + t.pass('client1 destroyed') + }) + client2.destroy(function () { + t.pass('client1 destroyed') + }) + } + } + + var client1 = new WebTorrent({ + dht: false, + tracker: false, + onWire: function (wire) { + t.pass('client1 onWire') + wire.use(Extension) + } + }) + var client2 = new WebTorrent({ + dht: false, + tracker: false, + onWire: function (wire) { + t.pass('client2 onWire') + wire.use(Extension) + } + }) + + client1.add(leavesTorrent, function (torrent1) { + client2.add(leavesTorrent.infoHash) + client2.on('listening', function (port, torrent2) { + torrent2.addPeer('127.0.0.1:' + client1.torrentPort) + }) + }) +})