bittorrent-protocol
Advanced tools
Comparing version 1.0.0 to 1.1.0
80
index.js
@@ -5,6 +5,6 @@ module.exports = Wire | ||
var bncode = require('bncode') | ||
var extend = require('extend.js') | ||
var inherits = require('inherits') | ||
var extend = require('extend.js') | ||
var speedometer = require('speedometer') | ||
var stream = require('stream') | ||
var speedometer = require('speedometer') | ||
@@ -57,3 +57,8 @@ var MESSAGE_PROTOCOL = new Buffer('\u0013BitTorrent protocol') | ||
this.extendedHandshake = {} | ||
this.peerExtendedHandshake = {} | ||
/** @type {Object} string -> function, ex 'ut_metadata' -> ut_metadata() */ | ||
this._ext = {} | ||
this._nextExt = 1 | ||
this.uploaded = 0 | ||
@@ -113,2 +118,42 @@ this.downloaded = 0 | ||
// | ||
// PROTOCOL EXTENSION API | ||
// | ||
Wire.prototype.use = function (Extension) { | ||
if (!Extension.name) { | ||
throw new Error('Extension API requires a named function, e.g. function name() {}') | ||
} | ||
var ext = this._nextExt | ||
var handler = new Extension(this) | ||
function noop () {} | ||
if (typeof handler.onHandshake !== 'function') { | ||
handler.onHandshake = noop | ||
} | ||
if (typeof handler.onExtendedHandshake !== 'function') { | ||
handler.onExtendedHandshake = noop | ||
} | ||
if (typeof handler.onMessage !== 'function') { | ||
handler.onMessage = noop | ||
} | ||
this.extendedMapping[ext] = Extension.name | ||
this._ext[Extension.name] = handler | ||
this._nextExt += 1 | ||
} | ||
/** | ||
* Return an extension's exported functions | ||
* @param {string} ext extension name | ||
* @return {Object} | ||
*/ | ||
Wire.prototype.ext = function (ext) { | ||
var self = this | ||
return this._ext[ext] | ||
} | ||
// | ||
// OUTGOING MESSAGES | ||
@@ -286,2 +331,6 @@ // | ||
this.peerExtensions = extensions | ||
for (var name in this._ext) { | ||
this._ext[name].onHandshake(infoHash, peerId, extensions) | ||
} | ||
this.emit('handshake', infoHash, peerId, extensions) | ||
@@ -291,8 +340,7 @@ | ||
* | ||
* Doing this after the 'handshake' event leaves users time to populate | ||
* `this.extendedHandshake` and `this.extendedMapping` which together form the message | ||
* that the remote wire will receive. | ||
* This comes after the 'handshake' event to give the user a chance to populate | ||
* `this.extendedHandshake` and `this.extendedMapping` before the extended handshake | ||
* is sent to the remote peer. | ||
*/ | ||
if (extensions.extended) { | ||
// Create extended message object from registered extensions | ||
@@ -379,11 +427,23 @@ var msg = extend({}, this.extendedHandshake) | ||
Wire.prototype._onExtended = function (ext, buf) { | ||
var info | ||
var info, name | ||
if (ext === 0 && (info = bncode.decode(buf))) { | ||
this.peerExtendedHandshake = info | ||
if (typeof info.m === 'object') { | ||
this.peerExtendedMapping = info.m | ||
for (name in info.m) { | ||
this.peerExtendedMapping[name] = Number(info.m[name].toString()) | ||
} | ||
} | ||
this.emit('extended', 'handshake', info) | ||
for (name in this._ext) { | ||
if (this.peerExtendedMapping[name]) { | ||
this._ext[name].onExtendedHandshake(this.peerExtendedHandshake) | ||
} | ||
} | ||
this.emit('extended', 'handshake', this.peerExtendedHandshake) | ||
} else { | ||
if (this.extendedMapping[ext]) { | ||
ext = this.extendedMapping[ext] | ||
ext = this.extendedMapping[ext] // friendly name for extension | ||
if (this._ext[ext]) { | ||
// there is an registered extension handler, so call it | ||
this._ext[ext].onMessage(buf) | ||
} | ||
} | ||
@@ -390,0 +450,0 @@ this.emit('extended', ext, buf) |
{ | ||
"name": "bittorrent-protocol", | ||
"description": "Simple, robust, BitTorrent peer wire protocol implementation", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"author": { | ||
@@ -6,0 +6,0 @@ "name": "Feross Aboukhadijeh", |
106
README.md
@@ -1,6 +0,2 @@ | ||
# bittorrent-protocol | ||
[![Build Status](http://img.shields.io/travis/feross/bittorrent-protocol.svg)](https://travis-ci.org/feross/bittorrent-protocol) | ||
[![NPM Version](http://img.shields.io/npm/v/bittorrent-protocol.svg)](https://npmjs.org/package/bittorrent-protocol) | ||
[![NPM](http://img.shields.io/npm/dm/bittorrent-protocol.svg)](https://npmjs.org/package/bittorrent-protocol) | ||
[![Gittip](http://img.shields.io/gittip/feross.svg)](https://www.gittip.com/feross/) | ||
# bittorrent-protocol [![build](http://img.shields.io/travis/feross/bittorrent-protocol.svg)](https://travis-ci.org/feross/bittorrent-protocol) [![npm](http://img.shields.io/npm/v/bittorrent-protocol.svg)](https://npmjs.org/package/bittorrent-protocol) [![gittip](http://img.shields.io/gittip/feross.svg)](https://www.gittip.com/feross/) | ||
@@ -11,5 +7,7 @@ ### Simple, robust, BitTorrent wire protocol implementation | ||
Node.js implementation of the [BitTorrent peer wire protocol](https://wiki.theory.org/BitTorrentSpecification#Peer_wire_protocol_.28TCP.29). The protocol is the main communication layer for BitTorrent file transfer. | ||
Node.js implementation of the [BitTorrent peer wire protocol](https://wiki.theory.org/BitTorrentSpecification#Peer_wire_protocol_.28TCP.29). | ||
The protocol is the main communication layer for BitTorrent file transfer. | ||
Also works in the browser with [browserify](http://browserify.org/)! This module is used by [WebTorrent](http://webtorrent.io). | ||
Also works in the browser with [browserify](http://browserify.org/)! This module is used | ||
by [WebTorrent](http://webtorrent.io). | ||
@@ -24,3 +22,4 @@ ## install | ||
The protocol is implemented as a **duplex stream**, so all you have to do is pipe to and from it. | ||
The protocol is implemented as a **duplex stream**, so all you have to do is pipe to and | ||
from it. | ||
@@ -163,7 +162,9 @@ duplex streams | a.pipe(b).pipe(a) | ||
If the timeout is triggered the request callback is called with an error and a `timeout` event is emitted. | ||
If the timeout is triggered the request callback is called with an error and a `timeout` | ||
event is emitted. | ||
### dht and port | ||
You can set the extensions flag `dht` in the handshake to `true` if you participate in the torrent dht. Afterwards you can send your dht port. | ||
You can set the extensions flag `dht` in the handshake to `true` if you participate in | ||
the torrent dht. Afterwards you can send your dht port. | ||
@@ -197,2 +198,26 @@ ```js | ||
### extension protocol (BEP 10) | ||
This module has built-in support for the | ||
[BitTorrent Extension Protocol (BEP 10)](http://www.bittorrent.org/beps/bep_0010.html). | ||
The intention of BEP 10 is to provide a simple and thin transport for extensions to the | ||
bittorrent protocol. Most extensions to the protocol use BEP 10 so they can add new | ||
features to the protocol without interfering with the standard bittorrent protocol or | ||
clients that don't support the new extension. | ||
An example of a BitTorrent extension that uses BEP 10 is | ||
[ut_metadata](http://www.bittorrent.org/beps/bep_0009.html) (BEP 9), the extension that | ||
allows magnet uris to work. | ||
```js | ||
wire.extended(code, buffer) | ||
``` | ||
This package, **bittorrent-protocol**, also provides a plugin API to make it easy to | ||
integrate extensions that use the extension protocol (BEP 10) into this module. For | ||
example, to support ut_metadata (BEP 9), you need only install the | ||
[ut_metadata](https://github.com/feross/ut_metadata) npm module and call `wire.use()`. | ||
See the [Plugin API](#plugin-api) section for more information. | ||
### transfer stats | ||
@@ -210,9 +235,66 @@ | ||
wire.on('download', function (numberOfBytes) { | ||
... | ||
... | ||
}) | ||
wire.on('upload', function (numberOfBytes) { | ||
... | ||
... | ||
}) | ||
``` | ||
## plugin api | ||
This package supports a simple plugin API so you can extend the default protocol | ||
functionality with common protocol extensions like ut_metadata (magnet uris). | ||
Here are the **bittorrent-protocol** plugins that we know about: | ||
- [ut_metadata](https://github.com/feross/ut_metadata) | ||
- **Add yours here! (Send a pull request! | ||
In short, a plugin can register itself with at a certain name, which will be added to the | ||
extended protocol handshake sent to the remote peer. Plugins can also hook events like | ||
'handshake' and 'extended'. To use a plugin, simply require it and call `wire.use()`. | ||
Here is an example of the **ut_metadata** plugin being used with **bittorrent-protocol**: | ||
```js | ||
net.createServer(function (socket) { | ||
var wire = new Protocol() | ||
socket.pipe(wire).pipe(socket) | ||
// initialize the extension | ||
wire.use(ut_metadata()) | ||
// all `ut_metadata` functionality can now be accessed at wire.ext('ut_metadata') | ||
// ask the peer to send us metadata | ||
wire.ext('ut_metadata').fetch() | ||
// 'metadata' event will fire when the metadata arrives and is verified to be correct! | ||
wire.ext('ut_metadata').on('metadata', function (metadata) { | ||
// got metadata! | ||
// Note: the event will not fire if the peer does not support ut_metadata, if they | ||
// don't have metadata yet either, if they repeatedly send invalid data, or if they | ||
// simply don't respond. | ||
}) | ||
// optionally, listen to the 'warning' event if you want to know that metadata is | ||
// probably not going to arrive for one of the above reasons. | ||
wire.ext('ut_metadata').on('warning', function (err) { | ||
console.log(err.message) | ||
}) | ||
// handle handshake | ||
wire.on('handshake', function (infoHash, peerId) { | ||
wire.handshake(new Buffer('my info hash'), new Buffer('my peer id')) | ||
}) | ||
}).listen(6881) | ||
``` | ||
If you want to write your own plugin, take a look at the | ||
[ut_metadata index.js file](https://github.com/feross/ut_metadata/blob/master/index.js) | ||
to see how it's done. | ||
## license | ||
@@ -219,0 +301,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
34251
759
300