BREAKING: opts.filter function is async; add createSwarm

- The expected signature for opts.filter is now:

function myFilterFn (infoHash, params, cb) {
  cb(infoHash === 'blah)
}

This allows interfacing with a database and fixes #80.

Also, swarm.getSwarm() is no longer responsible for creating a Swarm
instance, only returning an instance if there is already one. Creating
a swarm happens in swarm.createSwarm(). This change only affects users
who were override swarm.getSwarm().
This commit is contained in:
Feross Aboukhadijeh 2015-07-04 17:13:07 -07:00
parent 37f95b4b54
commit bf5b9f289a
2 changed files with 85 additions and 53 deletions

View File

@ -175,19 +175,19 @@ Server.prototype.close = function (cb) {
else cb(null)
}
Server.prototype.getSwarm = function (infoHash, params) {
Server.prototype.createSwarm = function (infoHash) {
var self = this
if (!params) params = {}
if (Buffer.isBuffer(infoHash)) infoHash = infoHash.toString('hex')
if (self._filter && !self._filter(infoHash, params)) return null
var swarm = self.torrents[infoHash]
if (!swarm) swarm = self.torrents[infoHash] = new Swarm(infoHash, self)
var swarm = self.torrents[infoHash] = new Swarm(infoHash, self)
return swarm
}
Server.prototype.getSwarm = function (infoHash) {
var self = this
if (Buffer.isBuffer(infoHash)) infoHash = infoHash.toString('hex')
return self.torrents[infoHash]
}
Server.prototype.onHttpRequest = function (req, res, opts) {
var self = this
if (!opts) opts = {}
@ -334,7 +334,10 @@ Server.prototype._onWebSocketRequest = function (socket, params) {
if (params.answer) {
debug('got answer %s from %s', JSON.stringify(params.answer), params.peer_id)
var swarm = self.getSwarm(params.info_hash, params)
var swarm = self.getSwarm(params.info_hash)
if (!swarm) {
return self.emit('warning', new Error('no swarm with that `info_hash`'))
}
var toPeer = swarm.peers[params.to_peer_id]
if (!toPeer) {
return self.emit('warning', new Error('no peer with that `to_peer_id`'))
@ -370,8 +373,28 @@ Server.prototype._onRequest = function (params, cb) {
Server.prototype._onAnnounce = function (params, cb) {
var self = this
var swarm = self.getSwarm(params.info_hash, params)
if (swarm === null) return cb(new Error('disallowed info_hash'))
var swarm = self.getSwarm(params.info_hash)
if (swarm) announce()
else createSwarm()
function createSwarm () {
if (self._filter) {
self._filter(params.info_hash, params, function (allowed) {
if (allowed) {
swarm = self.createSwarm(params.info_hash)
announce()
} else {
cb(new Error('disallowed info_hash'))
}
})
} else {
swarm = self.createSwarm(params.info_hash)
announce()
}
}
function announce () {
if (!params.event || params.event === 'empty') params.event = 'update'
swarm.announce(params, function (err, response) {
if (err) return cb(err)
@ -409,6 +432,8 @@ Server.prototype._onAnnounce = function (params, cb) {
})
}
}
Server.prototype._onScrape = function (params, cb) {
var self = this
@ -419,15 +444,20 @@ Server.prototype._onScrape = function (params, cb) {
}
series(params.info_hash.map(function (infoHash) {
var swarm = self.getSwarm(infoHash)
return function (cb) {
var swarm = self.getSwarm(infoHash)
if (swarm) {
swarm.scrape(params, function (err, scrapeInfo) {
cb(err, scrapeInfo && {
if (err) return cb(err)
cb(null, {
infoHash: infoHash,
complete: scrapeInfo.complete || 0,
incomplete: scrapeInfo.incomplete || 0
complete: (scrapeInfo && scrapeInfo.complete) || 0,
incomplete: (scrapeInfo && scrapeInfo.incomplete) || 0
})
})
} else {
cb(null, { infoHash: infoHash, complete: 0, incomplete: 0 })
}
}
}), function (err, results) {
if (err) return cb(err)
@ -440,9 +470,9 @@ Server.prototype._onScrape = function (params, cb) {
results.forEach(function (result) {
response.files[common.hexToBinary(result.infoHash)] = {
complete: result.complete,
incomplete: result.incomplete,
downloaded: result.complete // TODO: this only provides a lower-bound
complete: result.complete || 0,
incomplete: result.incomplete || 0,
downloaded: result.complete || 0 // TODO: this only provides a lower-bound
}
})

View File

@ -15,8 +15,10 @@ var peerId = new Buffer('01234567890123456789')
function testFilterOption (t, serverType) {
t.plan(6)
var opts = serverType === 'http' ? { udp: false } : { http: false }
opts.filter = function (infoHash) {
return infoHash !== parsedBitlove.infoHash
opts.filter = function (infoHash, params, cb) {
process.nextTick(function () {
cb(infoHash !== parsedBitlove.infoHash)
})
}
var server = new Server(opts)