11import arrayRemove from 'unordered-array-remove'
22import bencode from 'bencode'
3- import clone from 'clone'
43import Debug from 'debug'
5- import get from 'simple-get'
6- import Socks from 'socks'
4+ import fetch from 'cross-fetch-ponyfill'
75import { bin2hex , hex2bin , arr2text , text2arr , arr2hex } from 'uint8-util'
86
97import common from '../common.js'
@@ -13,6 +11,14 @@ import compact2string from 'compact2string'
1311const debug = Debug ( 'bittorrent-tracker:http-tracker' )
1412const HTTP_SCRAPE_SUPPORT = / ( \/ a n n (?: o u n c e ) ? ) [ ^ / ] * $ /
1513
14+ function abortTimeout ( ms ) {
15+ const controller = new AbortController ( )
16+ setTimeout ( ( ) => {
17+ controller . abort ( )
18+ } , ms ) . unref ?. ( )
19+ return controller
20+ }
21+
1622/**
1723 * HTTP torrent tracker client (for an individual tracker)
1824 *
@@ -112,70 +118,72 @@ class HTTPTracker extends Tracker {
112118 }
113119 }
114120
115- _request ( requestUrl , params , cb ) {
116- const self = this
121+ async _request ( requestUrl , params , cb ) {
117122 const parsedUrl = new URL ( requestUrl + ( requestUrl . indexOf ( '?' ) === - 1 ? '?' : '&' ) + common . querystringStringify ( params ) )
118123 let agent
119124 if ( this . client . _proxyOpts ) {
120125 agent = parsedUrl . protocol === 'https:' ? this . client . _proxyOpts . httpsAgent : this . client . _proxyOpts . httpAgent
121126 if ( ! agent && this . client . _proxyOpts . socksProxy ) {
122- agent = new Socks . Agent ( clone ( this . client . _proxyOpts . socksProxy ) , ( parsedUrl . protocol === 'https:' ) )
127+ agent = this . client . _proxyOpts . socksProxy
123128 }
124129 }
125130
126- this . cleanupFns . push ( cleanup )
127-
128- let request = get . concat ( {
129- url : parsedUrl . toString ( ) ,
130- agent,
131- timeout : common . REQUEST_TIMEOUT ,
132- headers : {
133- 'user-agent' : this . client . _userAgent || ''
134- }
135- } , onResponse )
136-
137- function cleanup ( ) {
138- if ( request ) {
139- arrayRemove ( self . cleanupFns , self . cleanupFns . indexOf ( cleanup ) )
140- request . abort ( )
141- request = null
131+ const cleanup = ( ) => {
132+ if ( ! controller . signal . aborted ) {
133+ arrayRemove ( this . cleanupFns , this . cleanupFns . indexOf ( cleanup ) )
134+ controller . abort ( )
135+ controller = null
142136 }
143- if ( self . maybeDestroyCleanup ) self . maybeDestroyCleanup ( )
137+ if ( this . maybeDestroyCleanup ) this . maybeDestroyCleanup ( )
144138 }
145139
146- function onResponse ( err , res , data ) {
147- cleanup ( )
148- if ( self . destroyed ) return
140+ this . cleanupFns . push ( cleanup )
149141
142+ let res
143+ let controller = abortTimeout ( common . REQUEST_TIMEOUT )
144+ try {
145+ res = await fetch ( parsedUrl . toString ( ) , {
146+ agent,
147+ signal : controller . signal ,
148+ dispatcher : agent ,
149+ headers : {
150+ 'user-agent' : this . client . _userAgent || ''
151+ }
152+ } )
153+ } catch ( err ) {
150154 if ( err ) return cb ( err )
151- if ( res . statusCode !== 200 ) {
152- return cb ( new Error ( `Non-200 response code ${ res . statusCode } from ${ self . announceUrl } ` ) )
153- }
154- if ( ! data || data . length === 0 ) {
155- return cb ( new Error ( `Invalid tracker response from${ self . announceUrl } ` ) )
156- }
157-
158- try {
159- data = bencode . decode ( data )
160- } catch ( err ) {
161- return cb ( new Error ( `Error decoding tracker response: ${ err . message } ` ) )
162- }
163- const failure = data [ 'failure reason' ] && arr2text ( data [ 'failure reason' ] )
164- if ( failure ) {
165- debug ( `failure from ${ requestUrl } (${ failure } )` )
166- return cb ( new Error ( failure ) )
167- }
155+ }
156+ let data = new Uint8Array ( await res . arrayBuffer ( ) )
157+ cleanup ( )
158+ if ( this . destroyed ) return
168159
169- const warning = data [ 'warning message' ] && arr2text ( data [ 'warning message' ] )
170- if ( warning ) {
171- debug ( `warning from ${ requestUrl } (${ warning } )` )
172- self . client . emit ( 'warning' , new Error ( warning ) )
173- }
160+ if ( res . status !== 200 ) {
161+ return cb ( new Error ( `Non-200 response code ${ res . statusCode } from ${ this . announceUrl } ` ) )
162+ }
163+ if ( ! data || data . length === 0 ) {
164+ return cb ( new Error ( `Invalid tracker response from${ this . announceUrl } ` ) )
165+ }
174166
175- debug ( `response from ${ requestUrl } ` )
167+ try {
168+ data = bencode . decode ( data )
169+ } catch ( err ) {
170+ return cb ( new Error ( `Error decoding tracker response: ${ err . message } ` ) )
171+ }
172+ const failure = data [ 'failure reason' ] && arr2text ( data [ 'failure reason' ] )
173+ if ( failure ) {
174+ debug ( `failure from ${ requestUrl } (${ failure } )` )
175+ return cb ( new Error ( failure ) )
176+ }
176177
177- cb ( null , data )
178+ const warning = data [ 'warning message' ] && arr2text ( data [ 'warning message' ] )
179+ if ( warning ) {
180+ debug ( `warning from ${ requestUrl } (${ warning } )` )
181+ this . client . emit ( 'warning' , new Error ( warning ) )
178182 }
183+
184+ debug ( `response from ${ requestUrl } ` )
185+
186+ cb ( null , data )
179187 }
180188
181189 _onAnnounceResponse ( data ) {
0 commit comments