Skip to content

Commit 8f65031

Browse files
committed
REFACTOR: separate distinct behaviours to modules
1 parent cbe4a3f commit 8f65031

File tree

4 files changed

+159
-169
lines changed

4 files changed

+159
-169
lines changed

services/statsRoute.js

Lines changed: 0 additions & 169 deletions
This file was deleted.

services/statsRoute/getStats.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
const peerid = require('bittorrent-peerid')
2+
3+
const get8Chars =
4+
peerId => Buffer.from(peerId, "hex")
5+
.toString()
6+
.substring(0, 8)
7+
8+
function addPeerClient( _clients, peer) {
9+
const clientId = peer.client.client;
10+
const client = _clients[clientId] || {};
11+
// If the client is not known show 8 chars from peerId as version
12+
const version = peer.client.version
13+
|| get8Chars(peer.peerId)
14+
15+
if (!client[version]) client[version] = 1
16+
else client[version]++
17+
18+
_clients[clientId] = client
19+
20+
return _clients
21+
}
22+
23+
function groupByClient(allPeers) {
24+
const clients =
25+
Object.values(allPeers)
26+
.reduce(addPeerClient, {})
27+
28+
return clients;
29+
}
30+
31+
const countPeers =
32+
allPeers =>
33+
filterFunction => {
34+
const filteredPeers =
35+
Object.values(allPeers).filter(filterFunction)
36+
37+
return filteredPeers.length
38+
}
39+
40+
const addPeer =
41+
peers =>
42+
(allPeers, peerId) => {
43+
// Don't mark the peer as most recently used for stats
44+
const peer = peers.peek(peerId)
45+
46+
if (peer == null) return // peers.peek() can evict the peer
47+
48+
const peerData = {
49+
peerId: peer.peerId,
50+
client: peerid(peer.peerId),
51+
ipv4: !peer.ip.includes(':'),
52+
ipv6: peer.ip.includes(':'),
53+
seeder: peer.complete,
54+
leecher: !peer.complete
55+
}
56+
57+
allPeers[peerId] = peerData
58+
59+
return allPeers
60+
}
61+
62+
const hasKeys = (torrent) => (torrent.peers.keys.length > 0)
63+
const countActiveTorrents = torrents => torrents.filter(hasKeys).length
64+
65+
const addTorrentKeys = (allPeers, torrent) => {
66+
const peers = torrent.peers
67+
const keys = peers.keys
68+
69+
const result = keys.reduce(addPeer(peers), allPeers)
70+
71+
return result
72+
}
73+
74+
const isSeederOnly = peer => (peer.seeder && peer.leecher === false)
75+
const isLeecherOnly = peer => (peer.leecher && peer.seeder === false)
76+
const isSeederAndLeecher = peer => (peer.seeder && peer.leecher)
77+
const isIPv4 = peer => peer.ipv4
78+
const isIPv6 = peer => peer.ipv6
79+
80+
const getStats = server => {
81+
const torrents = Object.values(server.torrents)
82+
const activeTorrents = countActiveTorrents(torrents)
83+
const allPeers = torrents.reduce(addTorrentKeys, {})
84+
const countAllPeers = countPeers(allPeers)
85+
86+
const stats = {
87+
torrents: torrents.length,
88+
activeTorrents,
89+
peersAll: Object.keys(allPeers).length,
90+
peersSeederOnly: countAllPeers(isSeederOnly),
91+
peersLeecherOnly: countAllPeers(isLeecherOnly),
92+
peersSeederAndLeecher: countAllPeers(isSeederAndLeecher),
93+
peersIPv4: countAllPeers(isIPv4),
94+
peersIPv6: countAllPeers(isIPv6),
95+
clients: groupByClient(allPeers)
96+
}
97+
98+
return stats
99+
}
100+
101+
module.exports = getStats

services/statsRoute/index.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const attachHttpServer = require('../attachHttp')
2+
const getStats = require('./getStats')
3+
const printClients = require('./printClients')
4+
5+
function setupStatsRoute(server, onListening) {
6+
if (!server.http) attachHttpServer(server, onListening);
7+
8+
// Http handler for '/stats' route
9+
server.http.on('request', (req, res) => {
10+
if (res.headersSent) return
11+
12+
if (req.method === 'GET' && (req.url === '/stats' || req.url === '/stats.json')) {
13+
const stats = getStats(server)
14+
if (req.url === '/stats.json' || req.headers.accept === 'application/json') {
15+
res.setHeader('Content-Type', 'application/json')
16+
res.end(JSON.stringify(stats))
17+
} else if (req.url === '/stats') {
18+
const printout = printClients(stats.clients)
19+
20+
res.setHeader('Content-Type', 'text/html')
21+
res.end(`
22+
<h1>${stats.torrents} torrents (${stats.activeTorrents} active)</h1>
23+
<h2>Connected Peers: ${stats.peersAll}</h2>
24+
<h3>Peers Seeding Only: ${stats.peersSeederOnly}</h3>
25+
<h3>Peers Leeching Only: ${stats.peersLeecherOnly}</h3>
26+
<h3>Peers Seeding & Leeching: ${stats.peersSeederAndLeecher}</h3>
27+
<h3>IPv4 Peers: ${stats.peersIPv4}</h3>
28+
<h3>IPv6 Peers: ${stats.peersIPv6}</h3>
29+
<h3>Clients:</h3>
30+
${printout}
31+
`.replace(/^\s+/gm, '')) // trim left
32+
}
33+
}
34+
})
35+
}
36+
37+
module.exports = setupStatsRoute
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const printVersionHtml = client => (html, version) => (
2+
html + `<li><strong>${name}</strong> ${version} : ${client[version]}</li>\n`
3+
)
4+
5+
function printClient(html, client) {
6+
const printClientHtml = printVersionHtml(client);
7+
const clientHtml =
8+
Object.values(client).reduce(printClientHtml, html)
9+
10+
return clientHtml;
11+
};
12+
13+
function printClients(clients) {
14+
const initialHtml = "<ul>\n";
15+
const contentHtml = Object.values(clients).reduce(printClient, initialHtml)
16+
const html = contentHtml + "</ul>"
17+
18+
return html
19+
}
20+
21+
module.exports = printClients

0 commit comments

Comments
 (0)