From edb5c6e8541586bf2815703bbf6c0ee9ffd80527 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Thu, 11 Dec 2014 12:53:39 -0800 Subject: [PATCH 1/2] code style --- lib/parse_http.js | 6 +++--- lib/parse_udp.js | 7 +++---- lib/swarm.js | 6 +++--- server.js | 13 ++++++------- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/lib/parse_http.js b/lib/parse_http.js index 85e3519..c6b67d7 100644 --- a/lib/parse_http.js +++ b/lib/parse_http.js @@ -1,16 +1,16 @@ +module.exports = parseHttpRequest + var common = require('./common') var REMOVE_IPV6_RE = /^::ffff:/ -module.exports = parseHttpRequest - function parseHttpRequest (req, options) { var s = req.url.split('?') var params = common.querystringParse(s[1]) if (s[0] === '/announce') { params.action = common.ACTIONS.ANNOUNCE - + params.peer_id = typeof params.peer_id === 'string' && common.binaryToUtf8(params.peer_id) params.port = Number(params.port) diff --git a/lib/parse_udp.js b/lib/parse_udp.js index 7e5ccdf..2122d96 100644 --- a/lib/parse_udp.js +++ b/lib/parse_udp.js @@ -1,10 +1,9 @@ +module.exports = parseUdpRequest + var bufferEqual = require('buffer-equal') var ipLib = require('ip') var common = require('./common') - -module.exports = parseUdpRequest - function parseUdpRequest (msg, rinfo) { if (msg.length < 16) { throw new Error('received packet is too short') @@ -20,7 +19,7 @@ function parseUdpRequest (msg, rinfo) { transactionId: msg.readUInt32BE(12) } - // TODO: randomize: + // TODO: randomize if (!bufferEqual(params.connectionId, common.CONNECTION_ID)) { throw new Error('received packet with invalid connection id') } diff --git a/lib/swarm.js b/lib/swarm.js index 40e4577..dc2c7e2 100644 --- a/lib/swarm.js +++ b/lib/swarm.js @@ -1,7 +1,7 @@ -var debug = require('debug')('bittorrent-tracker') - module.exports = Swarm +var debug = require('debug')('bittorrent-tracker') + // Regard this as the default implementation of an interface that you // need to support when overriding Server.getSwarm() function Swarm (infoHash, server) { @@ -110,7 +110,7 @@ Swarm.prototype._getPeers = function (numwant) { return peers } -Swarm.prototype.scrape = function (infoHash, params, cb) { +Swarm.prototype.scrape = function (params, cb) { cb(null, { complete: this.complete, incomplete: this.incomplete diff --git a/server.js b/server.js index ed1a229..af1dd49 100644 --- a/server.js +++ b/server.js @@ -147,7 +147,7 @@ Server.prototype._onHttpRequest = function (req, res) { // even though it's an error for the client, it's just a warning for the server. // don't crash the server because a client sent bad data :) self.emit('warning', error) - + return } @@ -185,7 +185,7 @@ Server.prototype._onUdpRequest = function (msg, rinfo) { 'failure reason': err.message } } - + var socket = dgram.createSocket('udp4') response.transactionId = params.transactionId response.connectionId = params.connectionId @@ -199,7 +199,6 @@ Server.prototype._onUdpRequest = function (msg, rinfo) { } Server.prototype._onRequest = function (params, cb) { - var response if (params && params.action === common.ACTIONS.CONNECT) { cb(null, { action: common.ACTIONS.CONNECT }) } else if (params && params.action === common.ACTIONS.ANNOUNCE) { @@ -230,7 +229,7 @@ Server.prototype._onAnnounce = function (params, cb) { Server.prototype._onScrape = function (params, cb) { var self = this - + if (typeof params.info_hash === 'string') { params.info_hash = [ params.info_hash ] } else if (params.info_hash == null) { @@ -238,13 +237,13 @@ Server.prototype._onScrape = function (params, cb) { // TODO: make this configurable! params.info_hash = Object.keys(self.torrents) } - + if (!Array.isArray(params.info_hash)) { var err = new Error('invalid info_hash') self.emit('warning', err) return cb(err) } - + var response = { action: common.ACTIONS.SCRAPE, files: {}, @@ -256,7 +255,7 @@ Server.prototype._onScrape = function (params, cb) { series(params.info_hash.map(function (infoHash) { var swarm = self.getSwarm(infoHash) return function (cb) { - swarm.scrape(infoHash, params, function (err, scrapeInfo) { + swarm.scrape(params, function (err, scrapeInfo) { cb(err, scrapeInfo && { infoHash: infoHash, complete: scrapeInfo.complete || 0, From c75ca05479f7635966e72fd2ee1d89d94f10ac40 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Thu, 11 Dec 2014 13:43:11 -0800 Subject: [PATCH 2/2] swarm.announce() should always call callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s important that calls to swarm.announce() always calls the callback that it’s passed otherwise http announce/scrape requests will hang (because res.end() is never called). Also, since this swarm implementation is in-memory, we can get rid of the callbacks to internal functions. Lastly, fixed references to non-existent start() function. --- lib/swarm.js | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/lib/swarm.js b/lib/swarm.js index dc2c7e2..b7c2baa 100644 --- a/lib/swarm.js +++ b/lib/swarm.js @@ -19,30 +19,27 @@ Swarm.prototype.announce = function (params, cb) { if (!params.event || params.event === 'empty') params.event = 'update' var fn = '_onAnnounce_' + params.event if (self[fn]) { - self[fn](params, peer, function (err) { - // event processed, prepare response: + self[fn](params, peer) // process event - if (params.left === 0 && peer) peer.complete = true + if (params.left === 0 && peer) peer.complete = true - // send peers - var peers = self._getPeers(params.numwant) - - cb(null, { - complete: self.complete, - incomplete: self.incomplete, - peers: peers - }) + cb(null, { + complete: self.complete, + incomplete: self.incomplete, + peers: self._getPeers(params.numwant) }) + } else { cb(new Error('invalid event')) } } -Swarm.prototype._onAnnounce_started = function (params, peer, cb) { +Swarm.prototype._onAnnounce_started = function (params, peer) { if (peer) { debug('unexpected `started` event from peer that is already in swarm') - return this._onAnnounce_update() // treat as an update + return this._onAnnounce_update(params, peer) // treat as an update } + if (params.left === 0) this.complete += 1 else this.incomplete += 1 peer = this.peers[params.addr] = { @@ -51,48 +48,42 @@ Swarm.prototype._onAnnounce_started = function (params, peer, cb) { peerId: params.peer_id } this.emit('start', params.addr) - - cb() } -Swarm.prototype._onAnnounce_stopped = function (params, peer, cb) { +Swarm.prototype._onAnnounce_stopped = function (params, peer) { if (!peer) { debug('unexpected `stopped` event from peer that is not in swarm') return // do nothing } + if (peer.complete) this.complete -= 1 else this.incomplete -= 1 this.peers[params.addr] = null this.emit('stop', params.addr) - - cb() } -Swarm.prototype._onAnnounce_completed = function (params, peer, cb) { +Swarm.prototype._onAnnounce_completed = function (params, peer) { if (!peer) { debug('unexpected `completed` event from peer that is not in swarm') - return start() // treat as a start + return this._onAnnounce_started(params, peer) // treat as a start } if (peer.complete) { debug('unexpected `completed` event from peer that is already marked as completed') return // do nothing } + this.complete += 1 this.incomplete -= 1 peer.complete = true this.emit('complete', params.addr) - - cb() } -Swarm.prototype._onAnnounce_update = function (params, peer, cb) { +Swarm.prototype._onAnnounce_update = function (params, peer) { if (!peer) { debug('unexpected `update` event from peer that is not in swarm') - return start() // treat as a start + return this._onAnnounce_started(params, peer) // treat as a start } this.emit('update', params.addr) - - cb() } Swarm.prototype._getPeers = function (numwant) {