@@ -28,25 +28,24 @@ inherits(Tracker, EventEmitter)
2828 * An individual torrent tracker
2929 *
3030 * @param {Client } client parent bittorrent tracker client
31- * @param {string } announceUrl announce url of tracker
32- * @param {Number } interval interval in ms to send announce requests to the tracker
31+ * @param {string } announceUrl announce url of tracker
3332 * @param {Object } opts optional options
3433 */
35- function Tracker ( client , announceUrl , interval , opts ) {
34+ function Tracker ( client , announceUrl , opts ) {
3635 var self = this
3736 EventEmitter . call ( self )
3837 self . _opts = opts || { }
39-
38+
4039 self . client = client
41-
40+
4241 self . _announceUrl = announceUrl
43- self . _intervalMs = interval
42+ self . _intervalMs = self . client . _intervalMs // use client interval initially
4443 self . _interval = null
45-
44+
4645 if ( self . _announceUrl . indexOf ( 'udp:' ) === 0 ) {
47- self . _requestImpl = self . _requestUdp . bind ( self )
46+ self . _requestImpl = self . _requestUdp
4847 } else {
49- self . _requestImpl = self . _requestHttp . bind ( self )
48+ self . _requestImpl = self . _requestHttp
5049 }
5150}
5251
@@ -55,7 +54,7 @@ Tracker.prototype.start = function (opts) {
5554 opts = opts || { }
5655 opts . event = 'started'
5756 self . _request ( opts )
58-
57+
5958 self . setInterval ( self . _intervalMs ) // start announcing on intervals
6059}
6160
@@ -64,7 +63,7 @@ Tracker.prototype.stop = function (opts) {
6463 opts = opts || { }
6564 opts . event = 'stopped'
6665 self . _request ( opts )
67-
66+
6867 self . setInterval ( 0 ) // stop announcing on intervals
6968}
7069
@@ -84,25 +83,25 @@ Tracker.prototype.update = function (opts) {
8483
8584Tracker . prototype . scrape = function ( opts ) {
8685 var self = this
87-
86+
8887 if ( ! self . _scrapeUrl ) {
8988 var announce = 'announce'
90- var i = self . _announceUrl . lastIndexOf ( '\ /' ) + 1
91-
89+ var i = self . _announceUrl . lastIndexOf ( '/' ) + 1
90+
9291 if ( i >= 1 && self . _announceUrl . slice ( i , i + announce . length ) === announce ) {
9392 self . _scrapeUrl = self . _announceUrl . slice ( 0 , i ) + 'scrape' + self . _announceUrl . slice ( i + announce . length )
9493 }
9594 }
96-
95+
9796 if ( ! self . _scrapeUrl ) {
9897 self . client . emit ( 'error' , new Error ( 'scrape not supported for announceUrl ' + self . _announceUrl ) )
9998 return
10099 }
101-
100+
102101 opts = extend ( {
103102 info_hash : bytewiseEncodeURIComponent ( self . client . _infoHash )
104103 } , opts )
105-
104+
106105 self . _requestImpl ( self . _scrapeUrl , opts )
107106}
108107
@@ -133,11 +132,11 @@ Tracker.prototype._request = function (opts) {
133132 uploaded : 0 , // default, user should provide real value
134133 downloaded : 0 // default, user should provide real value
135134 } , opts )
136-
135+
137136 if ( self . _trackerId ) {
138137 opts . trackerid = self . _trackerId
139138 }
140-
139+
141140 self . _requestImpl ( self . _announceUrl , opts )
142141}
143142
@@ -229,7 +228,7 @@ Tracker.prototype._requestUdp = function (requestUrl, opts) {
229228 clearTimeout ( timeout )
230229 socket . close ( )
231230 return
232-
231+
233232 case 2 : // scrape
234233 if ( message . length < 20 ) {
235234 return error ( 'invalid scrape message' )
@@ -258,7 +257,7 @@ Tracker.prototype._requestUdp = function (requestUrl, opts) {
258257 function genTransactionId ( ) {
259258 transactionId = new Buffer ( hat ( 32 ) , 'hex' )
260259 }
261-
260+
262261 function announce ( connectionId , opts ) {
263262 opts = opts || { }
264263 genTransactionId ( )
@@ -279,7 +278,7 @@ Tracker.prototype._requestUdp = function (requestUrl, opts) {
279278 toUInt16 ( self . client . _port || 0 )
280279 ] ) )
281280 }
282-
281+
283282 function scrape ( connectionId , opts ) {
284283 genTransactionId ( )
285284
@@ -315,7 +314,7 @@ Tracker.prototype._handleResponse = function (requestUrl, data) {
315314 if ( warning ) {
316315 self . client . emit ( 'warning' , warning ) ;
317316 }
318-
317+
319318 if ( requestUrl === self . _announceUrl ) {
320319 var interval = data . interval || data [ 'min interval' ]
321320 if ( interval && ! self . _opts . interval && self . _intervalMs !== 0 ) {
@@ -349,10 +348,10 @@ Tracker.prototype._handleResponse = function (requestUrl, data) {
349348 } )
350349 }
351350 } else if ( requestUrl === self . _scrapeUrl ) {
352- // note : the unofficial spec says to use the 'files' key but i've seen 'host' in practice
351+ // NOTE : the unofficial spec says to use the 'files' key but i've seen 'host' in practice
353352 data = data . files || data . host || { }
354353 data = data [ bytewiseEncodeURIComponent ( self . client . _infoHash ) ]
355-
354+
356355 if ( ! data ) {
357356 self . client . emit ( 'error' , new Error ( 'invalid scrape response' ) )
358357 } else {
@@ -401,7 +400,7 @@ function Client (peerId, port, torrent, opts) {
401400 self . _intervalMs = self . _opts . interval || ( 30 * 60 * 1000 ) // default: 30 minutes
402401
403402 self . _trackers = torrent . announce . map ( function ( announceUrl ) {
404- return Tracker ( self , announceUrl , self . _intervalMs , self . _opts )
403+ return new Tracker ( self , announceUrl , self . _opts )
405404 } )
406405}
407406
@@ -443,7 +442,7 @@ Client.prototype.scrape = function (opts) {
443442Client . prototype . setInterval = function ( intervalMs ) {
444443 var self = this
445444 self . _intervalMs = intervalMs
446-
445+
447446 self . _trackers . forEach ( function ( tracker ) {
448447 tracker . setInterval ( intervalMs )
449448 } )
@@ -522,27 +521,27 @@ Server.prototype._onHttpRequest = function (req, res) {
522521
523522 var warning
524523 var s = req . url . split ( '?' )
524+ var params = querystring . parse ( s [ 1 ] )
525525
526- if ( s [ 0 ] === '/announce' ) {
527- var params = querystring . parse ( s [ 1 ] )
526+ // TODO: detect when required params are missing
527+ // TODO: support multiple info_hash parameters as a concatenation of individual requests
528+ var infoHash = bytewiseDecodeURIComponent ( params . info_hash ) . toString ( 'hex' )
529+
530+ if ( ! infoHash ) {
531+ return error ( 'bittorrent-tracker server only supports announcing one torrent at a time' )
532+ }
528533
534+ if ( s [ 0 ] === '/announce' ) {
529535 var ip = self . _trustProxy
530536 ? req . headers [ 'x-forwarded-for' ] || req . connection . remoteAddress
531537 : req . connection . remoteAddress
532538 var port = Number ( params . port )
533539 var addr = ip + ':' + port
534-
535- // TODO: support multiple info_hash parameters as a concatenation of individual requests
536- var infoHash = bytewiseDecodeURIComponent ( params . info_hash ) . toString ( 'hex' )
537540 var peerId = bytewiseDecodeURIComponent ( params . peer_id ) . toString ( 'utf8' )
538-
539- if ( ! infoHash ) {
540- return error ( 'bittorrent-tracker server only supports announcing one torrent at a time' )
541- }
542-
541+
543542 var swarm = self . _getSwarm ( infoHash )
544543 var peer = swarm . peers [ addr ]
545-
544+
546545 switch ( params . event ) {
547546 case 'started' :
548547 if ( peer ) {
@@ -626,17 +625,11 @@ Server.prototype._onHttpRequest = function (req, res) {
626625 }
627626
628627 res . end ( bncode . encode ( response ) )
628+
629629 } else if ( s [ 0 ] === '/scrape' ) { // unofficial scrape message
630- var params = querystring . parse ( s [ 1 ] )
631- var infoHash = bytewiseDecodeURIComponent ( params . info_hash ) . toString ( 'hex' )
632-
633- if ( ! infoHash ) {
634- return error ( 'bittorrent-tracker server only supports scraping one torrent at a time' )
635- }
636-
637630 var swarm = self . _getSwarm ( infoHash )
638631 var response = { files : { } }
639-
632+
640633 response . files [ params . info_hash ] = {
641634 complete : swarm . complete ,
642635 incomplete : swarm . incomplete ,
@@ -645,7 +638,7 @@ Server.prototype._onHttpRequest = function (req, res) {
645638 min_request_interval : self . _interval
646639 }
647640 }
648-
641+
649642 res . end ( bncode . encode ( response ) )
650643 }
651644}
@@ -660,7 +653,7 @@ Server.prototype._getSwarm = function (infoHash) {
660653 peers : { }
661654 }
662655 }
663-
656+
664657 return swarm
665658}
666659
@@ -710,7 +703,9 @@ function toUInt32 (n) {
710703function toUInt64 ( n ) {
711704 if ( n > MAX_UINT || typeof n === 'string' ) {
712705 var bytes = bn ( n ) . toArray ( )
713- while ( bytes . length < 8 ) bytes . unshift ( 0 )
706+ while ( bytes . length < 8 ) {
707+ bytes . unshift ( 0 )
708+ }
714709 return new Buffer ( bytes )
715710 }
716711 return Buffer . concat ( [ toUInt32 ( 0 ) , toUInt32 ( n ) ] )
0 commit comments