Skip to content

Commit bf5b9f2

Browse files
committed
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 webtorrent#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().
1 parent 37f95b4 commit bf5b9f2

File tree

2 files changed

+86
-54
lines changed

2 files changed

+86
-54
lines changed

server.js

Lines changed: 82 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -175,19 +175,19 @@ Server.prototype.close = function (cb) {
175175
else cb(null)
176176
}
177177

178-
Server.prototype.getSwarm = function (infoHash, params) {
178+
Server.prototype.createSwarm = function (infoHash) {
179179
var self = this
180-
if (!params) params = {}
181180
if (Buffer.isBuffer(infoHash)) infoHash = infoHash.toString('hex')
182-
183-
if (self._filter && !self._filter(infoHash, params)) return null
184-
185-
var swarm = self.torrents[infoHash]
186-
if (!swarm) swarm = self.torrents[infoHash] = new Swarm(infoHash, self)
187-
181+
var swarm = self.torrents[infoHash] = new Swarm(infoHash, self)
188182
return swarm
189183
}
190184

185+
Server.prototype.getSwarm = function (infoHash) {
186+
var self = this
187+
if (Buffer.isBuffer(infoHash)) infoHash = infoHash.toString('hex')
188+
return self.torrents[infoHash]
189+
}
190+
191191
Server.prototype.onHttpRequest = function (req, res, opts) {
192192
var self = this
193193
if (!opts) opts = {}
@@ -334,7 +334,10 @@ Server.prototype._onWebSocketRequest = function (socket, params) {
334334
if (params.answer) {
335335
debug('got answer %s from %s', JSON.stringify(params.answer), params.peer_id)
336336

337-
var swarm = self.getSwarm(params.info_hash, params)
337+
var swarm = self.getSwarm(params.info_hash)
338+
if (!swarm) {
339+
return self.emit('warning', new Error('no swarm with that `info_hash`'))
340+
}
338341
var toPeer = swarm.peers[params.to_peer_id]
339342
if (!toPeer) {
340343
return self.emit('warning', new Error('no peer with that `to_peer_id`'))
@@ -370,43 +373,65 @@ Server.prototype._onRequest = function (params, cb) {
370373

371374
Server.prototype._onAnnounce = function (params, cb) {
372375
var self = this
373-
var swarm = self.getSwarm(params.info_hash, params)
374-
if (swarm === null) return cb(new Error('disallowed info_hash'))
375-
if (!params.event || params.event === 'empty') params.event = 'update'
376-
swarm.announce(params, function (err, response) {
377-
if (err) return cb(err)
378-
379-
if (!response.action) response.action = common.ACTIONS.ANNOUNCE
380-
if (!response.interval) response.interval = Math.ceil(self._intervalMs / 1000)
381-
382-
if (params.compact === 1) {
383-
var peers = response.peers
384376

385-
// Find IPv4 peers
386-
response.peers = string2compact(peers.filter(function (peer) {
387-
return common.IPV4_RE.test(peer.ip)
388-
}).map(function (peer) {
389-
return peer.ip + ':' + peer.port
390-
}))
391-
// Find IPv6 peers
392-
response.peers6 = string2compact(peers.filter(function (peer) {
393-
return common.IPV6_RE.test(peer.ip)
394-
}).map(function (peer) {
395-
return '[' + peer.ip + ']:' + peer.port
396-
}))
397-
} else if (params.compact === 0) {
398-
// IPv6 peers are not separate for non-compact responses
399-
response.peers = response.peers.map(function (peer) {
400-
return {
401-
'peer id': peer.peerId,
402-
ip: peer.ip,
403-
port: peer.port
377+
var swarm = self.getSwarm(params.info_hash)
378+
if (swarm) announce()
379+
else createSwarm()
380+
381+
function createSwarm () {
382+
if (self._filter) {
383+
self._filter(params.info_hash, params, function (allowed) {
384+
if (allowed) {
385+
swarm = self.createSwarm(params.info_hash)
386+
announce()
387+
} else {
388+
cb(new Error('disallowed info_hash'))
404389
}
405390
})
406-
} // else, return full peer objects (used for websocket responses)
391+
} else {
392+
swarm = self.createSwarm(params.info_hash)
393+
announce()
394+
}
395+
}
396+
397+
function announce () {
398+
if (!params.event || params.event === 'empty') params.event = 'update'
399+
swarm.announce(params, function (err, response) {
400+
if (err) return cb(err)
401+
402+
if (!response.action) response.action = common.ACTIONS.ANNOUNCE
403+
if (!response.interval) response.interval = Math.ceil(self._intervalMs / 1000)
404+
405+
if (params.compact === 1) {
406+
var peers = response.peers
407+
408+
// Find IPv4 peers
409+
response.peers = string2compact(peers.filter(function (peer) {
410+
return common.IPV4_RE.test(peer.ip)
411+
}).map(function (peer) {
412+
return peer.ip + ':' + peer.port
413+
}))
414+
// Find IPv6 peers
415+
response.peers6 = string2compact(peers.filter(function (peer) {
416+
return common.IPV6_RE.test(peer.ip)
417+
}).map(function (peer) {
418+
return '[' + peer.ip + ']:' + peer.port
419+
}))
420+
} else if (params.compact === 0) {
421+
// IPv6 peers are not separate for non-compact responses
422+
response.peers = response.peers.map(function (peer) {
423+
return {
424+
'peer id': peer.peerId,
425+
ip: peer.ip,
426+
port: peer.port
427+
}
428+
})
429+
} // else, return full peer objects (used for websocket responses)
430+
431+
cb(err, response)
432+
})
433+
}
407434

408-
cb(err, response)
409-
})
410435
}
411436

412437
Server.prototype._onScrape = function (params, cb) {
@@ -419,15 +444,20 @@ Server.prototype._onScrape = function (params, cb) {
419444
}
420445

421446
series(params.info_hash.map(function (infoHash) {
422-
var swarm = self.getSwarm(infoHash)
423447
return function (cb) {
424-
swarm.scrape(params, function (err, scrapeInfo) {
425-
cb(err, scrapeInfo && {
426-
infoHash: infoHash,
427-
complete: scrapeInfo.complete || 0,
428-
incomplete: scrapeInfo.incomplete || 0
448+
var swarm = self.getSwarm(infoHash)
449+
if (swarm) {
450+
swarm.scrape(params, function (err, scrapeInfo) {
451+
if (err) return cb(err)
452+
cb(null, {
453+
infoHash: infoHash,
454+
complete: (scrapeInfo && scrapeInfo.complete) || 0,
455+
incomplete: (scrapeInfo && scrapeInfo.incomplete) || 0
456+
})
429457
})
430-
})
458+
} else {
459+
cb(null, { infoHash: infoHash, complete: 0, incomplete: 0 })
460+
}
431461
}
432462
}), function (err, results) {
433463
if (err) return cb(err)
@@ -440,9 +470,9 @@ Server.prototype._onScrape = function (params, cb) {
440470

441471
results.forEach(function (result) {
442472
response.files[common.hexToBinary(result.infoHash)] = {
443-
complete: result.complete,
444-
incomplete: result.incomplete,
445-
downloaded: result.complete // TODO: this only provides a lower-bound
473+
complete: result.complete || 0,
474+
incomplete: result.incomplete || 0,
475+
downloaded: result.complete || 0 // TODO: this only provides a lower-bound
446476
}
447477
})
448478

test/filter.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ var peerId = new Buffer('01234567890123456789')
1515
function testFilterOption (t, serverType) {
1616
t.plan(6)
1717
var opts = serverType === 'http' ? { udp: false } : { http: false }
18-
opts.filter = function (infoHash) {
19-
return infoHash !== parsedBitlove.infoHash
18+
opts.filter = function (infoHash, params, cb) {
19+
process.nextTick(function () {
20+
cb(infoHash !== parsedBitlove.infoHash)
21+
})
2022
}
2123
var server = new Server(opts)
2224

0 commit comments

Comments
 (0)