diff options
author | Feross Aboukhadijeh <feross@feross.org> | 2014-02-24 06:45:31 +0400 |
---|---|---|
committer | Feross Aboukhadijeh <feross@feross.org> | 2014-02-24 06:45:31 +0400 |
commit | 70d6a18c0b078e39fd59e5bfc9e53307097c0d96 (patch) | |
tree | ea7817359486f35a34a3bf66a30c2648e7e50021 /lib/torrent.js | |
parent | df7be73a9327ed8f6d62912269f00035c2931f61 (diff) |
clean up metadata fetching code (BEP 9) (#27)
Diffstat (limited to 'lib/torrent.js')
-rw-r--r-- | lib/torrent.js | 158 |
1 files changed, 87 insertions, 71 deletions
diff --git a/lib/torrent.js b/lib/torrent.js index 5a9c988..a5536ac 100644 --- a/lib/torrent.js +++ b/lib/torrent.js @@ -9,6 +9,10 @@ var Swarm = require('bittorrent-swarm') var METADATA_BLOCK_SIZE = 16 * 1024 var WIRE_TIMEOUT = 10000 +var EXTENDED_MESSAGES = { + ut_metadata: 1 +} + inherits(Torrent, EventEmitter) function Torrent (uri, opts) { @@ -66,12 +70,14 @@ Torrent.prototype._onWire = function (wire) { wire.setKeepAlive(true) // If peer supports DHT, send PORT message to report DHT node listening port - if (wire.peerExtensions.dht) + if (wire.peerExtensions.dht) { + console.log(wire.remoteAddress, 'supports DHT') wire.port(self.dhtPort) + } // When peer sends PORT, add them to the routing table wire.on('port', function (port) { - console.log('received PORT: ', port) + console.log(wire.remoteAddress, 'port', port) // TODO: DHT doesn't have a routing table yet // dht.add(wire.remoteAddress, port) }) @@ -82,12 +88,10 @@ Torrent.prototype._onWire = function (wire) { // Support extended messages: // - ut_metadata (metadata fetching, trackerless torrents) if (wire.peerExtensions.extended) { - console.log(wire.remoteAddress + ' supports extended messages', wire.peerExtensions) + console.log(wire.remoteAddress, 'supports extended messages', wire.peerExtensions) var extendedMessage = { - m: { - ut_metadata: 1 - } + m: EXTENDED_MESSAGES } // Only send metadata_size if we have complete metadata @@ -98,76 +102,88 @@ Torrent.prototype._onWire = function (wire) { } wire.on('extended', function (ext, buf) { - var dict - console.log('Received extended message ' + ext + ' from ' + wire.remoteAddress) - - if (ext === 0) { // handshake + console.log(wire.remoteAddress, 'extended', ext) - try { - console.log('decoding ' + buf.toString()) - dict = bncode.decode(buf.toString()) - console.log('got extended handshake: ' + JSON.stringify(dict)) - } catch (e) { - console.error('Error decoding extended message: ' + e.message) - } + if (ext === 0) // 0 = handshake + self._onExtendedHandshake(wire, buf) + else if (ext === EXTENDED_MESSAGES.ut_metadata) + self._onUtMetadata(wire, buf) + }) +} - if (dict.m.ut_metadata && dict.metadata_size) { - var metadataSize = dict.metadata_size - var numPieces = Math.ceil(metadataSize / METADATA_BLOCK_SIZE) - console.log('metadata size: ' + metadataSize) - console.log(numPieces + ' pieces') - - wire.metadata = new Buffer(metadataSize) - - // request all pieces - for (var piece = 0; piece < numPieces; piece++) { - wire.extended(dict.m.ut_metadata, { - msg_type: 0, - piece: piece - }) - } - } +Torrent.prototype._onExtendedHandshake = function (wire, buf) { + var self = this + var dict + try { + dict = bncode.decode(buf.toString()) + console.log(wire.remoteAddress, 'extended handshake' + JSON.stringify(dict)) + } catch (e) { + console.error(wire.remoteAddress, 'extended handshake error', e.message) + return + } + if (!dict) return + + // If torrent is missing metadata and peer supports ut_metadata extension, + // then request all metadata pieces + if (!self.metadata && dict.metadata_size && dict.m && dict.m.ut_metadata) { + var numPieces = Math.ceil(dict.metadata_size / METADATA_BLOCK_SIZE) + wire.metadata = new Buffer(dict.metadata_size) + + console.log('metadata size: ' + dict.metadata_size) + console.log(numPieces + ' pieces') + + // request all pieces + for (var piece = 0; piece < numPieces; piece++) { + wire.extended(dict.m.ut_metadata, { + msg_type: 0, + piece: piece + }) + } + } +} - } else if (ext === 1) { // ut_metadata - - // 0 - request - // 1 - data - // 2 - reject - - var str - var dataIndex - var data - try { - str = buf.toString() - console.log('decoding ' + str) - dataIndex = str.indexOf('ee') + 2 - var msg = str.substring(0, dataIndex) - console.log('using ' + msg) - dict = bncode.decode(msg) - data = buf.slice(dataIndex) - console.log('got metadata: ' + JSON.stringify(dict)) - console.log('got metadata data: ' + data.length + ' bytes') - } catch (e) { - console.error('Error decoding extended message: ' + e.message) - } +// 0 - request +// 1 - data +// 2 - reject +Torrent.prototype._onUtMetadata = function (wire, buf) { + var self = this - // {'msg_type': 1, 'piece': 0, 'total_size': 3425} - if (dict.msg_type === 1) { // data - console.log('total_size: ' + dict.total_size) - data.copy(wire.metadata, dict.piece * METADATA_BLOCK_SIZE) - - console.log('METADATA') - console.log(wire.metadata.toString()) - self.metadata = { - 'announce-list': [], - info: bncode.decode(wire.metadata), - // info_hash: - } - console.log(self.metadata) - self.emit('metadata', this.metadata) + var dict + var data + try { + var str = buf.toString() + var dataIndex = str.indexOf('ee') + 2 + dict = bncode.decode(str.substring(0, dataIndex)) + data = buf.slice(dataIndex) + console.log(wire.remoteAddress, 'ut_metadata', JSON.stringify(dict), 'metadata byte length', data.length) + } catch (e) { + console.error('Error decoding extended message: ' + e.message) + } + if (!dict) return + + switch (dict.msg_type) { + // ut_metadata request (from peer) + // example: {'msg_type': 0, 'piece': 0} + case 0: + // TODO + break + // ut_metadata data (in response to our request) + // example: {'msg_type': 1, 'piece': 0, 'total_size': 3425} + case 1: + data.copy(wire.metadata, dict.piece * METADATA_BLOCK_SIZE) + + self.metadata = { + 'announce-list': [], + info: bncode.decode(wire.metadata) } - } - }) + self.emit('metadata', this.metadata) + break + // ut_metadata reject (peer doesn't have piece we requested) + // {'msg_type': 2, 'piece': 0} + case 2: + // TODO + break + } } // |