Skip to content

Commit 89b3fb3

Browse files
committed
support custom filter error messages
In addition to returning a boolean (`true` for allowed, `false` for disallowed), you can return an `Error` object to disallow and provide a custom reason. Fixes webtorrent#85
1 parent f13accf commit 89b3fb3

File tree

3 files changed

+118
-31
lines changed

3 files changed

+118
-31
lines changed

README.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,18 @@ var server = new Server({
113113
http: true, // enable http server? [default=true]
114114
ws: true, // enable websocket server? [default=false]
115115
filter: function (infoHash, params, cb) {
116-
// black/whitelist for disallowing/allowing torrents [default=allow all]
117-
// this example only allows this one torrent
118-
cb(infoHash === 'aaa67059ed6bd08362da625b3ae77f6f4a075aaa')
116+
// Blacklist/whitelist function for allowing/disallowing torrents. If this option is
117+
// omitted, all torrents are allowed. It is possible to interface with a database or
118+
// external system before deciding to allow/deny, because this function is async.
119119

120-
// it's possible to interface with a database or external system before
121-
// deciding, because this function is async
120+
// It is possible to block by peer id (whitelisting torrent clients) or by secret
121+
// key (private trackers). Full access to the original HTTP/UDP request parameters
122+
// are available n `params`.
122123

123-
// it's possible to block by peer id (whitelisting torrent clients) or
124-
// by secret key, as you get full access to the original http/udp
125-
// request parameters in `params`
124+
// This example only allows one torrent.
125+
126+
var allowed = (infoHash === 'aaa67059ed6bd08362da625b3ae77f6f4a075aaa')
127+
cb(allowed)
126128
})
127129
})
128130

server.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -385,11 +385,13 @@ Server.prototype._onAnnounce = function (params, cb) {
385385
function createSwarm () {
386386
if (self._filter) {
387387
self._filter(params.info_hash, params, function (allowed) {
388-
if (allowed) {
388+
if (allowed instanceof Error) {
389+
cb(allowed)
390+
} else if (!allowed) {
391+
cb(new Error('disallowed info_hash'))
392+
} else {
389393
swarm = self.createSwarm(params.info_hash)
390394
announce()
391-
} else {
392-
cb(new Error('disallowed info_hash'))
393395
}
394396
})
395397
} else {
@@ -432,7 +434,7 @@ Server.prototype._onAnnounce = function (params, cb) {
432434
})
433435
} // else, return full peer objects (used for websocket responses)
434436

435-
cb(err, response)
437+
cb(null, response)
436438
})
437439
}
438440

test/filter.js

Lines changed: 102 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ var parsedLeaves = parseTorrent(leaves)
1313
var peerId = new Buffer('01234567890123456789')
1414

1515
function testFilterOption (t, serverType) {
16-
t.plan(6)
16+
t.plan(8)
1717
var opts = serverType === 'http' ? { udp: false } : { http: false }
1818
opts.filter = function (infoHash, params, cb) {
1919
process.nextTick(function () {
@@ -44,29 +44,33 @@ function testFilterOption (t, serverType) {
4444
client.once('warning', function (err) {
4545
t.ok(/disallowed info_hash/.test(err.message), 'got client warning')
4646

47-
client.destroy()
48-
client = new Client(peerId, port, parsedLeaves)
47+
client.destroy(function () {
48+
t.pass('client destroyed')
49+
client = new Client(peerId, port, parsedLeaves)
4950

50-
client.on('error', function (err) {
51-
t.error(err)
52-
})
53-
client.on('warning', function (err) {
54-
t.error(err)
55-
})
51+
client.on('error', function (err) {
52+
t.error(err)
53+
})
54+
client.on('warning', function (err) {
55+
t.error(err)
56+
})
5657

57-
client.on('update', function () {
58-
t.pass('got announce')
59-
client.destroy()
60-
server.close(function () {
61-
t.pass('server closed')
58+
client.on('update', function () {
59+
t.pass('got announce')
60+
client.destroy(function () {
61+
t.pass('client destroyed')
62+
})
63+
server.close(function () {
64+
t.pass('server closed')
65+
})
6266
})
63-
})
6467

65-
server.on('start', function () {
66-
t.equal(Object.keys(server.torrents).length, 1)
67-
})
68+
server.on('start', function () {
69+
t.equal(Object.keys(server.torrents).length, 1)
70+
})
6871

69-
client.start()
72+
client.start()
73+
})
7074
})
7175

7276
server.once('warning', function (err) {
@@ -85,3 +89,82 @@ test('http: filter option blocks tracker from tracking torrent', function (t) {
8589
test('udp: filter option blocks tracker from tracking torrent', function (t) {
8690
testFilterOption(t, 'udp')
8791
})
92+
93+
function testFilterCustomError (t, serverType) {
94+
t.plan(8)
95+
var opts = serverType === 'http' ? { udp: false } : { http: false }
96+
opts.filter = function (infoHash, params, cb) {
97+
process.nextTick(function () {
98+
if (infoHash === parsedBitlove.infoHash) cb(new Error('bitlove blocked'))
99+
else cb(true)
100+
})
101+
}
102+
var server = new Server(opts)
103+
104+
server.on('error', function (err) {
105+
t.error(err)
106+
})
107+
108+
server.listen(0, function () {
109+
var port = server[serverType].address().port
110+
var announceUrl = serverType === 'http'
111+
? 'http://127.0.0.1:' + port + '/announce'
112+
: 'udp://127.0.0.1:' + port
113+
114+
parsedBitlove.announce = [ announceUrl ]
115+
parsedLeaves.announce = [ announceUrl ]
116+
117+
var client = new Client(peerId, port, parsedBitlove)
118+
119+
client.on('error', function (err) {
120+
t.error(err)
121+
})
122+
123+
client.once('warning', function (err) {
124+
t.ok(/bitlove blocked/.test(err.message), 'got client warning')
125+
126+
client.destroy(function () {
127+
t.pass('client destroyed')
128+
client = new Client(peerId, port, parsedLeaves)
129+
130+
client.on('error', function (err) {
131+
t.error(err)
132+
})
133+
client.on('warning', function (err) {
134+
t.error(err)
135+
})
136+
137+
client.on('update', function () {
138+
t.pass('got announce')
139+
client.destroy(function () {
140+
t.pass('client destroyed')
141+
})
142+
server.close(function () {
143+
t.pass('server closed')
144+
})
145+
})
146+
147+
server.on('start', function () {
148+
t.equal(Object.keys(server.torrents).length, 1)
149+
})
150+
151+
client.start()
152+
})
153+
})
154+
155+
server.once('warning', function (err) {
156+
t.ok(/bitlove blocked/.test(err.message), 'got server warning')
157+
t.equal(Object.keys(server.torrents).length, 0)
158+
})
159+
160+
client.start()
161+
})
162+
}
163+
164+
test('http: filter option with custom error', function (t) {
165+
testFilterCustomError(t, 'http')
166+
})
167+
168+
test('udp: filter option filter option with custom error', function (t) {
169+
testFilterCustomError(t, 'udp')
170+
})

0 commit comments

Comments
 (0)