diff --git a/torrent.go b/torrent.go index 3c0bcb09..1849dbcf 100644 --- a/torrent.go +++ b/torrent.go @@ -1431,7 +1431,7 @@ func (t *Torrent) startScrapingTracker(_url string) { } cl.activeAnnounces[urlString] = struct{}{} }, - done: func() { + done: func(slowdown bool) { cl.lock() defer cl.unlock() delete(cl.activeAnnounces, urlString) diff --git a/tracker/tracker.go b/tracker/tracker.go index 5497037f..65cad803 100644 --- a/tracker/tracker.go +++ b/tracker/tracker.go @@ -73,7 +73,8 @@ func (me Announce) Do() (res AnnounceResponse, err error) { } if me.Context == nil { // This is just to maintain the old behaviour that should be a timeout of 15s. Users can - // override it by providing their own Context. + // override it by providing their own Context. See comments elsewhere about longer timeouts + // acting as rate limiting overloaded trackers. ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() me.Context = ctx diff --git a/tracker_scraper.go b/tracker_scraper.go index 62ca4261..27018398 100644 --- a/tracker_scraper.go +++ b/tracker_scraper.go @@ -2,7 +2,6 @@ package torrent import ( "bytes" - "context" "errors" "fmt" "net" @@ -21,7 +20,10 @@ type trackerScraper struct { u url.URL t *Torrent lastAnnounce trackerAnnounceResult - allow, done func() + allow func() + // The slowdown argument lets us indicate if we think there should be some backpressure on + // access to the tracker. It doesn't necessarily have to be used. + done func(slowdown bool) } type torrentTrackerAnnouncer interface { @@ -111,7 +113,10 @@ func (me *trackerScraper) announce(event tracker.AnnounceEvent) (ret trackerAnno }() ret.Interval = time.Minute me.allow() - defer me.done() + // We might pass true if we got an error. Currently we don't because timing out with a + // reasonably long timeout is its own form of backpressure (it remains to be seen if it's + // enough). + defer me.done(false) ip, err := me.getIp() if err != nil { ret.Err = fmt.Errorf("error getting ip: %s", err) @@ -120,11 +125,13 @@ func (me *trackerScraper) announce(event tracker.AnnounceEvent) (ret trackerAnno me.t.cl.rLock() req := me.t.announceRequest(event) me.t.cl.rUnlock() - ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) - defer cancel() + // The default timeout is currently 15s, and that works well as backpressure on concurrent + // access to the tracker. + //ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + //defer cancel() me.t.logger.WithDefaultLevel(log.Debug).Printf("announcing to %q: %#v", me.u.String(), req) res, err := tracker.Announce{ - Context: ctx, + //Context: ctx, HTTPProxy: me.t.cl.config.HTTPProxy, UserAgent: me.t.cl.config.HTTPUserAgent, TrackerUrl: me.trackerUrl(ip), @@ -136,7 +143,7 @@ func (me *trackerScraper) announce(event tracker.AnnounceEvent) (ret trackerAnno ClientIp6: krpc.NodeAddr{IP: me.t.cl.config.PublicIp6}, }.Do() if err != nil { - ret.Err = fmt.Errorf("error announcing: %s", err) + ret.Err = fmt.Errorf("announcing: %w", err) return } me.t.AddPeers(peerInfos(nil).AppendFromTracker(res.Peers))