Skip to content

Commit 9dfc24d

Browse files
author
Rich Jones
committed
Refactor changes per #issuecomment-257912499, adds a trustIp specific test function
1 parent 6e0dea5 commit 9dfc24d

File tree

2 files changed

+169
-5
lines changed

2 files changed

+169
-5
lines changed

lib/server/parse-http.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,18 @@ function parseHttpRequest (req, opts) {
3131
common.MAX_ANNOUNCE_PEERS
3232
)
3333

34-
params.ip = opts.trustIp
35-
? params.ip || opts.trustProxy
36-
? req.headers['x-forwarded-for'] || req.connection.remoteAddress.replace(common.REMOVE_IPV4_MAPPED_IPV6_RE, '') // force IPv4
37-
: req.connection.remoteAddress.replace(common.REMOVE_IPV4_MAPPED_IPV6_RE, '')
38-
: req.connection.remoteAddress.replace(common.REMOVE_IPV4_MAPPED_IPV6_RE, '')
34+
// If we're trusting IPs supplied in the GET parameters, simply use that if available
35+
if (opts.trustIp && params.ip) {
36+
// No operation needed
37+
// Else, if we're trusting proxied headers, use that value if available,
38+
} else if (opts.trustProxy && req.headers['x-forwarded-for']) {
39+
params.ip = req.headers['x-forwarded-for']
40+
// Otherwise, simply use the connection's remote host address.
41+
} else {
42+
params.ip = req.connection.remoteAddress
43+
// Remove IPv4-Mapped address prefix from IPv6 address if present
44+
.replace(common.REMOVE_IPV4_MAPPED_IPV6_RE, '')
45+
}
3946
params.addr = (common.IPV6_RE.test(params.ip) ? '[' + params.ip + ']' : params.ip) + ':' + params.port
4047

4148
params.headers = req.headers

test/server.js

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,160 @@ test('http ipv6 server', function (t) {
178178
test('udp server', function (t) {
179179
serverTest(t, 'udp', 'inet')
180180
})
181+
182+
function serverTestTrustIP (t, serverType, serverFamily) {
183+
t.plan(32)
184+
185+
var hostname = serverFamily === 'inet6'
186+
? '[::1]'
187+
: '127.0.0.1'
188+
var customIp = 'custom.ip.address.or.hostname'
189+
190+
var opts = {
191+
serverType: serverType,
192+
peersCacheLength: 2,
193+
trustIp: true
194+
}
195+
196+
common.createServer(t, opts, function (server) {
197+
var port = server[serverType].address().port
198+
var announceUrl = serverType + '://' + hostname + ':' + port + '/announce'
199+
200+
var client1 = new Client({
201+
infoHash: infoHash,
202+
announce: [ announceUrl ],
203+
peerId: peerId,
204+
port: 6881,
205+
getAnnounceOpts: function () {
206+
// provide a callback that will be called whenever announce() is called
207+
// internally (on timer), or by the user
208+
return {
209+
uploaded: 0,
210+
downloaded: 0,
211+
left: 0,
212+
ip: customIp,
213+
customParam: 'blah' // custom parameters supported
214+
}
215+
}
216+
// wrtc: wrtc
217+
})
218+
219+
client1.start()
220+
221+
server.once('start', function () {
222+
t.pass('got start message from client1')
223+
})
224+
225+
client1.once('update', function (data) {
226+
t.equal(data.announce, announceUrl)
227+
t.equal(data.complete, 0)
228+
t.equal(data.incomplete, 1)
229+
230+
server.getSwarm(infoHash, function (err, swarm) {
231+
t.error(err)
232+
233+
t.equal(Object.keys(server.torrents).length, 1)
234+
t.equal(swarm.complete, 0)
235+
t.equal(swarm.incomplete, 1)
236+
t.equal(swarm.peers.length, 1)
237+
238+
var id = serverType === 'ws'
239+
? peerId.toString('hex')
240+
: customIp + ':6881'
241+
242+
var peer = swarm.peers.peek(id)
243+
244+
t.equal(peer.type, serverType)
245+
t.equal(peer.ip, customIp)
246+
t.equal(peer.peerId, peerId.toString('hex'))
247+
t.equal(peer.complete, false)
248+
if (serverType === 'ws') {
249+
t.equal(typeof peer.port, 'number')
250+
t.ok(peer.socket)
251+
} else {
252+
t.equal(peer.port, 6881)
253+
t.notOk(peer.socket)
254+
}
255+
256+
client1.complete()
257+
258+
client1.once('update', function (data) {
259+
t.equal(data.announce, announceUrl)
260+
t.equal(data.complete, 1)
261+
t.equal(data.incomplete, 0)
262+
263+
client1.scrape()
264+
265+
client1.once('scrape', function (data) {
266+
t.equal(data.announce, announceUrl)
267+
t.equal(typeof data.complete, 'number')
268+
t.equal(typeof data.incomplete, 'number')
269+
t.equal(typeof data.downloaded, 'number')
270+
271+
var client2 = new Client({
272+
infoHash: infoHash,
273+
announce: [ announceUrl ],
274+
peerId: peerId2,
275+
port: 6882
276+
// wrtc: wrtc
277+
})
278+
279+
client2.start()
280+
281+
server.once('start', function () {
282+
t.pass('got start message from client2')
283+
})
284+
285+
client2.once('peer', function (addr) {
286+
t.ok(addr === hostname + ':6881' || addr === hostname + ':6882' || addr.id === peerId.toString('hex'))
287+
288+
swarm.peers.once('evict', function (evicted) {
289+
t.equals(evicted.value.peerId, peerId.toString('hex'))
290+
})
291+
var client3 = new Client({
292+
infoHash: infoHash,
293+
announce: [ announceUrl ],
294+
peerId: peerId3,
295+
port: 6880
296+
// wrtc: wrtc
297+
})
298+
client3.start()
299+
300+
server.once('start', function () {
301+
t.pass('got start message from client3')
302+
})
303+
304+
client3.once('update', function () {
305+
client2.stop()
306+
client2.once('update', function (data) {
307+
t.equal(data.announce, announceUrl)
308+
t.equal(data.complete, 1)
309+
t.equal(data.incomplete, 1)
310+
client2.destroy()
311+
312+
client3.stop()
313+
client3.once('update', function (data) {
314+
t.equal(data.announce, announceUrl)
315+
t.equal(data.complete, 1)
316+
t.equal(data.incomplete, 0)
317+
318+
client3.destroy(function () {
319+
client1.destroy(function () {
320+
server.close()
321+
})
322+
// if (serverType === 'ws') wrtc.close()
323+
})
324+
})
325+
})
326+
})
327+
})
328+
})
329+
})
330+
})
331+
})
332+
})
333+
}
334+
335+
test('http ipv4 server', function (t) {
336+
serverTestTrustIP(t, 'http', 'inet')
337+
})

0 commit comments

Comments
 (0)