Skip to content

Commit f8c7de5

Browse files
committed
Add stats on clients based on peerIds
1 parent bbb8edc commit f8c7de5

File tree

3 files changed

+95
-6
lines changed

3 files changed

+95
-6
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
},
2222
"dependencies": {
2323
"bencode": "^0.10.0",
24+
"bittorrent-peerid": "^1.0.2",
2425
"bn.js": "^4.4.0",
2526
"compact2string": "^1.2.0",
2627
"debug": "^2.0.0",

server.js

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ var dgram = require('dgram')
77
var EventEmitter = require('events').EventEmitter
88
var http = require('http')
99
var inherits = require('inherits')
10+
var peerid = require('bittorrent-peerid')
1011
var series = require('run-series')
1112
var string2compact = require('string2compact')
1213
var WebSocketServer = require('ws').Server
@@ -150,6 +151,43 @@ function Server (opts) {
150151
return count
151152
}
152153

154+
function groupByClient () {
155+
var clients = {}
156+
for (var key in allPeers) {
157+
if (allPeers.hasOwnProperty(key)) {
158+
var peer = allPeers[key]
159+
160+
if (!clients[peer.client.client]) {
161+
clients[peer.client.client] = {}
162+
}
163+
var client = clients[peer.client.client]
164+
// If the client is not known show 8 chars from peerId as version
165+
var version = peer.client.version || new Buffer(peer.peerId, 'hex').toString().substring(0, 8)
166+
if (!client[version]) {
167+
client[version] = 0
168+
}
169+
client[version]++
170+
}
171+
}
172+
return clients
173+
}
174+
175+
function printClients (clients) {
176+
var html = '<ul>\n'
177+
for (var name in clients) {
178+
if (clients.hasOwnProperty(name)) {
179+
var client = clients[name]
180+
for (var version in client) {
181+
if (client.hasOwnProperty(version)) {
182+
html += '<li><strong>' + name + '</strong> ' + version + ' : ' + client[version] + '</li>\n'
183+
}
184+
}
185+
}
186+
}
187+
html += '</ul>'
188+
return html
189+
}
190+
153191
if (req.method === 'GET' && (req.url === '/stats' || req.url === '/stats.json')) {
154192
infoHashes.forEach(function (infoHash) {
155193
var peers = self.torrents[infoHash].peers
@@ -176,6 +214,8 @@ function Server (opts) {
176214
} else {
177215
allPeers[peerId].leecher = true
178216
}
217+
allPeers[peerId].peerId = peer.peerId
218+
allPeers[peerId].client = peerid(peer.peerId)
179219
})
180220
})
181221

@@ -193,7 +233,8 @@ function Server (opts) {
193233
peersLeecherOnly: countPeers(isLeecherOnly),
194234
peersSeederAndLeecher: countPeers(isSeederAndLeecher),
195235
peersIPv4: countPeers(isIPv4),
196-
peersIPv6: countPeers(isIPv6)
236+
peersIPv6: countPeers(isIPv6),
237+
clients: groupByClient()
197238
}
198239

199240
if (req.url === '/stats.json' || req.headers['content-type'] === 'application/json') {
@@ -206,7 +247,10 @@ function Server (opts) {
206247
'<h3>Peers Leeching Only: ' + stats.peersLeecherOnly + '</h3>\n' +
207248
'<h3>Peers Seeding & Leeching: ' + stats.peersSeederAndLeecher + '</h3>\n' +
208249
'<h3>IPv4 Peers: ' + stats.peersIPv4 + '</h3>\n' +
209-
'<h3>IPv6 Peers: ' + stats.peersIPv6 + '</h3>\n')
250+
'<h3>IPv6 Peers: ' + stats.peersIPv6 + '</h3>\n' +
251+
'<h3>Clients:</h3>\n' +
252+
printClients(stats.clients)
253+
)
210254
}
211255
}
212256
})

test/stats.js

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@ var fixtures = require('webtorrent-fixtures')
55
var get = require('simple-get')
66
var test = require('tape')
77

8-
var peerId = Buffer.from('01234567890123456789')
8+
var peerId = Buffer.from('-WW0091-4ea5886ce160')
9+
var unknownPeerId = Buffer.from('01234567890123456789')
910

1011
function parseHtml (html) {
1112
var extractValue = new RegExp('[^v^h](\\d+)')
1213
var array = html.replace('torrents', '\n').split('\n').filter(function (line) {
1314
return line && line.trim().length > 0
1415
}).map(function (line) {
1516
var a = extractValue.exec(line)
16-
return parseInt(a[1])
17+
if (a) {
18+
return parseInt(a[1])
19+
}
1720
})
1821
var i = 0
1922
return {
@@ -111,7 +114,7 @@ test('server: get empty stats on stats.json', function (t) {
111114
})
112115

113116
test('server: get leecher stats.json', function (t) {
114-
t.plan(10)
117+
t.plan(11)
115118

116119
commonTest.createServer(t, 'http', function (server, announceUrl) {
117120
// announce a torrent to the tracker
@@ -134,7 +137,6 @@ test('server: get leecher stats.json', function (t) {
134137

135138
get.concat(opts, function (err, res, stats) {
136139
t.error(err)
137-
console.log(stats)
138140

139141
t.equal(res.statusCode, 200)
140142
t.equal(stats.torrents, 1)
@@ -143,6 +145,48 @@ test('server: get leecher stats.json', function (t) {
143145
t.equal(stats.peersSeederOnly, 0)
144146
t.equal(stats.peersLeecherOnly, 1)
145147
t.equal(stats.peersSeederAndLeecher, 0)
148+
t.equal(stats.clients['WebTorrent']['0.0.9.1'], 1)
149+
150+
client.destroy(function () { t.pass('client destroyed') })
151+
server.close(function () { t.pass('server closed') })
152+
})
153+
})
154+
})
155+
})
156+
157+
test('server: get leecher stats.json (unknown peerId)', function (t) {
158+
t.plan(11)
159+
160+
commonTest.createServer(t, 'http', function (server, announceUrl) {
161+
// announce a torrent to the tracker
162+
var client = new Client({
163+
infoHash: fixtures.leaves.parsedTorrent.infoHash,
164+
announce: announceUrl,
165+
peerId: unknownPeerId,
166+
port: 6881
167+
})
168+
client.on('error', function (err) { t.error(err) })
169+
client.on('warning', function (err) { t.error(err) })
170+
171+
client.start()
172+
173+
server.once('start', function () {
174+
var opts = {
175+
url: announceUrl.replace('/announce', '/stats.json'),
176+
json: true
177+
}
178+
179+
get.concat(opts, function (err, res, stats) {
180+
t.error(err)
181+
182+
t.equal(res.statusCode, 200)
183+
t.equal(stats.torrents, 1)
184+
t.equal(stats.activeTorrents, 1)
185+
t.equal(stats.peersAll, 1)
186+
t.equal(stats.peersSeederOnly, 0)
187+
t.equal(stats.peersLeecherOnly, 1)
188+
t.equal(stats.peersSeederAndLeecher, 0)
189+
t.equal(stats.clients['unknown']['01234567'], 1)
146190

147191
client.destroy(function () { t.pass('client destroyed') })
148192
server.close(function () { t.pass('server closed') })

0 commit comments

Comments
 (0)