@@ -136,147 +136,148 @@ class Server extends EventEmitter {
136136 }
137137
138138 // Http handler for '/stats' route
139- this . http . on ( 'request' , ( req , res ) => {
140- if ( res . headersSent ) return
139+ this . http . on ( 'request' , this . onStats ) ;
140+ }
141+
142+ let num = ! ! this . http + ! ! this . udp4 + ! ! this . udp6
143+ const self = this
144+ function onListening ( ) {
145+ num -= 1
146+ if ( num === 0 ) {
147+ self . listening = true
148+ debug ( 'listening' )
149+ self . emit ( 'listening' )
150+ }
151+ }
152+ }
141153
142- const infoHashes = Object . keys ( this . torrents )
143- let activeTorrents = 0
144- const allPeers = { }
154+ onStats = ( req , res ) => {
155+ if ( res . headersSent ) return
145156
146- function countPeers ( filterFunction ) {
147- let count = 0
148- let key
157+ const infoHashes = Object . keys ( this . torrents )
158+ let activeTorrents = 0
159+ const allPeers = { }
149160
150- for ( key in allPeers ) {
151- if ( hasOwnProperty . call ( allPeers , key ) && filterFunction ( allPeers [ key ] ) ) {
152- count ++
153- }
154- }
161+ function countPeers ( filterFunction ) {
162+ let count = 0
163+ let key
155164
156- return count
165+ for ( key in allPeers ) {
166+ if ( hasOwnProperty . call ( allPeers , key ) && filterFunction ( allPeers [ key ] ) ) {
167+ count ++
157168 }
169+ }
158170
159- function groupByClient ( ) {
160- const clients = { }
161- for ( const key in allPeers ) {
162- if ( hasOwnProperty . call ( allPeers , key ) ) {
163- const peer = allPeers [ key ]
164-
165- if ( ! clients [ peer . client . client ] ) {
166- clients [ peer . client . client ] = { }
167- }
168- const client = clients [ peer . client . client ]
169- // If the client is not known show 8 chars from peerId as version
170- const version = peer . client . version || Buffer . from ( peer . peerId , 'hex' ) . toString ( ) . substring ( 0 , 8 )
171- if ( ! client [ version ] ) {
172- client [ version ] = 0
173- }
174- client [ version ] ++
175- }
171+ return count
172+ }
173+
174+ function groupByClient ( ) {
175+ const clients = { }
176+ for ( const key in allPeers ) {
177+ if ( hasOwnProperty . call ( allPeers , key ) ) {
178+ const peer = allPeers [ key ]
179+
180+ if ( ! clients [ peer . client . client ] ) {
181+ clients [ peer . client . client ] = { }
182+ }
183+ const client = clients [ peer . client . client ]
184+ // If the client is not known show 8 chars from peerId as version
185+ const version = peer . client . version || Buffer . from ( peer . peerId , 'hex' ) . toString ( ) . substring ( 0 , 8 )
186+ if ( ! client [ version ] ) {
187+ client [ version ] = 0
176188 }
177- return clients
189+ client [ version ] ++
178190 }
191+ }
192+ return clients
193+ }
179194
180- function printClients ( clients ) {
181- let html = '<ul>\n'
182- for ( const name in clients ) {
183- if ( hasOwnProperty . call ( clients , name ) ) {
184- const client = clients [ name ]
185- for ( const version in client ) {
186- if ( hasOwnProperty . call ( client , version ) ) {
187- html += `<li><strong>${ name } </strong> ${ version } : ${ client [ version ] } </li>\n`
188- }
189- }
195+ function printClients ( clients ) {
196+ let html = '<ul>\n'
197+ for ( const name in clients ) {
198+ if ( hasOwnProperty . call ( clients , name ) ) {
199+ const client = clients [ name ]
200+ for ( const version in client ) {
201+ if ( hasOwnProperty . call ( client , version ) ) {
202+ html += `<li><strong>${ name } </strong> ${ version } : ${ client [ version ] } </li>\n`
190203 }
191204 }
192- html += '</ul>'
193- return html
194205 }
206+ }
207+ html += '</ul>'
208+ return html
209+ }
195210
196- if ( req . method === 'GET' && ( req . url === '/stats' || req . url === '/stats.json' ) ) {
197- infoHashes . forEach ( infoHash => {
198- const peers = this . torrents [ infoHash ] . peers
199- const keys = peers . keys
200- if ( keys . length > 0 ) activeTorrents ++
201-
202- keys . forEach ( peerId => {
203- // Don't mark the peer as most recently used for stats
204- const peer = peers . peek ( peerId )
205- if ( peer == null ) return // peers.peek() can evict the peer
206-
207- if ( ! hasOwnProperty . call ( allPeers , peerId ) ) {
208- allPeers [ peerId ] = {
209- ipv4 : false ,
210- ipv6 : false ,
211- seeder : false ,
212- leecher : false
213- }
214- }
215-
216- if ( peer . ip . includes ( ':' ) ) {
217- allPeers [ peerId ] . ipv6 = true
218- } else {
219- allPeers [ peerId ] . ipv4 = true
220- }
221-
222- if ( peer . complete ) {
223- allPeers [ peerId ] . seeder = true
224- } else {
225- allPeers [ peerId ] . leecher = true
226- }
227-
228- allPeers [ peerId ] . peerId = peer . peerId
229- allPeers [ peerId ] . client = peerid ( peer . peerId )
230- } )
231- } )
211+ if ( req . method === 'GET' && ( req . url === '/stats' || req . url === '/stats.json' ) ) {
212+ infoHashes . forEach ( infoHash => {
213+ const peers = this . torrents [ infoHash ] . peers
214+ const keys = peers . keys
215+ if ( keys . length > 0 ) activeTorrents ++
216+
217+ keys . forEach ( peerId => {
218+ // Don't mark the peer as most recently used for stats
219+ const peer = peers . peek ( peerId )
220+ if ( peer == null ) return // peers.peek() can evict the peer
221+
222+ if ( ! hasOwnProperty . call ( allPeers , peerId ) ) {
223+ allPeers [ peerId ] = {
224+ ipv4 : false ,
225+ ipv6 : false ,
226+ seeder : false ,
227+ leecher : false
228+ }
229+ }
232230
233- const isSeederOnly = peer => { return peer . seeder && peer . leecher === false }
234- const isLeecherOnly = peer => { return peer . leecher && peer . seeder === false }
235- const isSeederAndLeecher = peer => { return peer . seeder && peer . leecher }
236- const isIPv4 = peer => { return peer . ipv4 }
237- const isIPv6 = peer => { return peer . ipv6 }
238-
239- const stats = {
240- torrents : infoHashes . length ,
241- activeTorrents,
242- peersAll : Object . keys ( allPeers ) . length ,
243- peersSeederOnly : countPeers ( isSeederOnly ) ,
244- peersLeecherOnly : countPeers ( isLeecherOnly ) ,
245- peersSeederAndLeecher : countPeers ( isSeederAndLeecher ) ,
246- peersIPv4 : countPeers ( isIPv4 ) ,
247- peersIPv6 : countPeers ( isIPv6 ) ,
248- clients : groupByClient ( )
231+ if ( peer . ip . includes ( ':' ) ) {
232+ allPeers [ peerId ] . ipv6 = true
233+ } else {
234+ allPeers [ peerId ] . ipv4 = true
249235 }
250236
251- if ( req . url === '/stats.json' || req . headers . accept === 'application/json' ) {
252- res . setHeader ( 'Content-Type' , 'application/json' )
253- res . end ( JSON . stringify ( stats ) )
254- } else if ( req . url === '/stats' ) {
255- res . setHeader ( 'Content-Type' , 'text/html' )
256- res . end ( `
257- <h1>${ stats . torrents } torrents (${ stats . activeTorrents } active)</h1>
258- <h2>Connected Peers: ${ stats . peersAll } </h2>
259- <h3>Peers Seeding Only: ${ stats . peersSeederOnly } </h3>
260- <h3>Peers Leeching Only: ${ stats . peersLeecherOnly } </h3>
261- <h3>Peers Seeding & Leeching: ${ stats . peersSeederAndLeecher } </h3>
262- <h3>IPv4 Peers: ${ stats . peersIPv4 } </h3>
263- <h3>IPv6 Peers: ${ stats . peersIPv6 } </h3>
264- <h3>Clients:</h3>
265- ${ printClients ( stats . clients ) }
266- ` . replace ( / ^ \s + / gm, '' ) ) // trim left
237+ if ( peer . complete ) {
238+ allPeers [ peerId ] . seeder = true
239+ } else {
240+ allPeers [ peerId ] . leecher = true
267241 }
268- }
242+
243+ allPeers [ peerId ] . peerId = peer . peerId
244+ allPeers [ peerId ] . client = peerid ( peer . peerId )
245+ } )
269246 } )
270- }
271247
272- let num = ! ! this . http + ! ! this . udp4 + ! ! this . udp6
273- const self = this
274- function onListening ( ) {
275- num -= 1
276- if ( num === 0 ) {
277- self . listening = true
278- debug ( 'listening' )
279- self . emit ( 'listening' )
248+ const isSeederOnly = peer => { return peer . seeder && peer . leecher === false }
249+ const isLeecherOnly = peer => { return peer . leecher && peer . seeder === false }
250+ const isSeederAndLeecher = peer => { return peer . seeder && peer . leecher }
251+ const isIPv4 = peer => { return peer . ipv4 }
252+ const isIPv6 = peer => { return peer . ipv6 }
253+
254+ const stats = {
255+ torrents : infoHashes . length ,
256+ activeTorrents,
257+ peersAll : Object . keys ( allPeers ) . length ,
258+ peersSeederOnly : countPeers ( isSeederOnly ) ,
259+ peersLeecherOnly : countPeers ( isLeecherOnly ) ,
260+ peersSeederAndLeecher : countPeers ( isSeederAndLeecher ) ,
261+ peersIPv4 : countPeers ( isIPv4 ) ,
262+ peersIPv6 : countPeers ( isIPv6 ) ,
263+ clients : groupByClient ( )
264+ }
265+
266+ if ( req . url === '/stats.json' || req . headers . accept === 'application/json' ) {
267+ res . write ( JSON . stringify ( stats ) )
268+ res . end ( )
269+ } else if ( req . url === '/stats' ) {
270+ res . end ( `
271+ <h1>${ stats . torrents } torrents (${ stats . activeTorrents } active)</h1>
272+ <h2>Connected Peers: ${ stats . peersAll } </h2>
273+ <h3>Peers Seeding Only: ${ stats . peersSeederOnly } </h3>
274+ <h3>Peers Leeching Only: ${ stats . peersLeecherOnly } </h3>
275+ <h3>Peers Seeding & Leeching: ${ stats . peersSeederAndLeecher } </h3>
276+ <h3>IPv4 Peers: ${ stats . peersIPv4 } </h3>
277+ <h3>IPv6 Peers: ${ stats . peersIPv6 } </h3>
278+ <h3>Clients:</h3>
279+ ${ printClients ( stats . clients ) }
280+ ` . replace ( / ^ \s + / gm, '' ) ) // trim left
280281 }
281282 }
282283 }
@@ -363,6 +364,10 @@ class Server extends EventEmitter {
363364 onHttpRequest ( req , res , opts = { } ) {
364365 opts . trustProxy = opts . trustProxy || this . _trustProxy
365366
367+ if ( req . originalUrl === "/stats" || req . originalUrl === "/stats.json" ) {
368+ return this . onStats ( req , res ) ;
369+ }
370+
366371 let params
367372 try {
368373 params = parseHttpRequest ( req , opts )
0 commit comments