Skip to content

Commit 74f9cda

Browse files
committed
Merge pull request webtorrent#142 from DiegoRBaquero/master
Web-based tracker statistics. Fix webtorrent#74
2 parents 1563f75 + 035994c commit 74f9cda

File tree

3 files changed

+88
-1
lines changed

3 files changed

+88
-1
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ This module is used by [WebTorrent](http://webtorrent.io).
3232
- Robust and well-tested
3333
- Comprehensive test suite (runs entirely offline, so it's reliable)
3434
- Used by popular clients: [WebTorrent](http://webtorrent.io), [peerflix](https://github.com/mafintosh/peerflix), and [playback](https://mafintosh.github.io/playback/)
35+
- Web-Based Statistics
3536

3637
Also see [bittorrent-dht](https://github.com/feross/bittorrent-dht).
3738

@@ -143,6 +144,7 @@ var server = new Server({
143144
udp: true, // enable udp server? [default=true]
144145
http: true, // enable http server? [default=true]
145146
ws: true, // enable websocket server? [default=true]
147+
stats: true, // enable web-based statistics [default=true]
146148
filter: function (infoHash, params, cb) {
147149
// Blacklist/whitelist function for allowing/disallowing torrents. If this option is
148150
// omitted, all torrents are allowed. It is possible to interface with a database or

bin/cmd.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ var argv = minimist(process.argv.slice(2), {
1919
'trust-proxy',
2020
'udp',
2121
'version',
22-
'ws'
22+
'ws',
23+
'no-stats'
2324
],
2425
string: [
2526
'http-hostname',
@@ -56,6 +57,7 @@ if (argv.help) {
5657
--http enable http server
5758
--udp enable udp server
5859
--ws enable websocket server
60+
--no-stats disable web-based statistics
5961
-q, --quiet only show error output
6062
-s, --silent show no output
6163
-v, --version print the current version
@@ -75,9 +77,12 @@ argv.http = allFalsy || argv.http
7577
argv.udp = allFalsy || argv.udp
7678
argv.ws = allFalsy || argv.ws
7779

80+
argv['no-stats'] = !!argv['no-stats']
81+
7882
var server = new Server({
7983
http: argv.http,
8084
interval: argv.interval,
85+
stats: argv['no-stats'],
8186
trustProxy: argv['trust-proxy'],
8287
udp: argv.udp,
8388
ws: argv.ws
@@ -133,4 +138,10 @@ server.listen(argv.port, hostname, function () {
133138
var wsPort = wsAddr.port
134139
console.log('WebSocket tracker: ws://' + wsHost + ':' + wsPort)
135140
}
141+
if (server.http && argv['no-stats'] && !argv.quiet) {
142+
var statsAddr = server.http.address()
143+
var statsHost = statsAddr.address !== '::' ? statsAddr.address : 'localhost'
144+
var statsPort = statsAddr.port
145+
console.log('Tracker statistics: http://' + statsHost + ':' + statsPort)
146+
}
136147
})

server.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,80 @@ function Server (opts) {
120120
self.ws.on('connection', function (socket) { self.onWebSocketConnection(socket) })
121121
}
122122

123+
if (opts.stats !== false) {
124+
if (!self.http) {
125+
self.http = http.createServer()
126+
self.http.on('error', function (err) { self._onError(err) })
127+
self.http.on('listening', onListening)
128+
}
129+
130+
// Http handler for '/stats' route
131+
self.http.on('request', function (req, res, opts) {
132+
if (res.headersSent) return
133+
134+
var infoHashes = Object.keys(self.torrents)
135+
var activeTorrents = 0
136+
var allPeers = {}
137+
138+
function countPeers (filterFunction) {
139+
var count = 0
140+
var key
141+
142+
for (key in allPeers) {
143+
if (allPeers.hasOwnProperty(key) && filterFunction(allPeers[key])) {
144+
count++
145+
}
146+
}
147+
148+
return count
149+
}
150+
151+
if (req.method === 'GET' && req.url === '/stats') {
152+
infoHashes.forEach(function (infoHash) {
153+
var peers = self.torrents[infoHash].peers
154+
var keys = Object.keys(peers)
155+
if (keys.length > 0) activeTorrents++
156+
157+
keys.forEach(function (peerId) {
158+
if (!allPeers.hasOwnProperty(peerId)) {
159+
allPeers[peerId] = {
160+
ipv4: false,
161+
ipv6: false,
162+
seeder: false,
163+
leecher: false
164+
}
165+
}
166+
var peer = peers[peerId]
167+
if (peer.ip.indexOf(':') >= 0) {
168+
allPeers[peerId].ipv6 = true
169+
} else {
170+
allPeers[peerId].ipv4 = true
171+
}
172+
if (peer.complete) {
173+
allPeers[peerId].seeder = true
174+
} else {
175+
allPeers[peerId].leecher = true
176+
}
177+
})
178+
})
179+
180+
var isSeederOnly = function (peer) { return peer.seeder && peer.leecher === false }
181+
var isLeecherOnly = function (peer) { return peer.leecher && peer.seeder === false }
182+
var isSeederAndLeecher = function (peer) { return peer.seeder && peer.leecher }
183+
var isIPv4 = function (peer) { return peer.ipv4 }
184+
var isIPv6 = function (peer) { return peer.ipv6 }
185+
186+
res.end('<h1>' + infoHashes.length + ' torrents (' + activeTorrents + ' active)</h1>\n' +
187+
'<h2>Connected Peers: ' + Object.keys(allPeers).length + '</h2>\n' +
188+
'<h3>Peers Seeding Only: ' + countPeers(isSeederOnly) + '</h3>\n' +
189+
'<h3>Peers Leeching Only: ' + countPeers(isLeecherOnly) + '</h3>\n' +
190+
'<h3>Peers Seeding & Leeching: ' + countPeers(isSeederAndLeecher) + '</h3>\n' +
191+
'<h3>IPv4 Peers: ' + countPeers(isIPv4) + '</h3>\n' +
192+
'<h3>IPv6 Peers: ' + countPeers(isIPv6) + '</h3>\n')
193+
}
194+
})
195+
}
196+
123197
var num = !!self.http + !!self.udp4 + !!self.udp6
124198
function onListening () {
125199
num -= 1

0 commit comments

Comments
 (0)