]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Strictly adher to tracker announce response intervals if a torrent is private
authorMatt Joiner <anacrolix@gmail.com>
Wed, 9 Dec 2020 11:36:57 +0000 (22:36 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Wed, 9 Dec 2020 11:36:57 +0000 (22:36 +1100)
t.go
tracker_scraper.go

diff --git a/t.go b/t.go
index 9d7ce2855e9d26c6e586b911ff46433c66279ee3..a0b5cb59a55070eb4fdbae394640e2b318ceed3e 100644 (file)
--- a/t.go
+++ b/t.go
@@ -16,6 +16,7 @@ func (t *Torrent) InfoHash() metainfo.Hash {
 
 // Returns a channel that is closed when the info (.Info()) for the torrent has become available.
 func (t *Torrent) GotInfo() <-chan struct{} {
+       // TODO: We shouldn't need to lock to take a channel here, if the event is only ever set.
        t.cl.lock()
        defer t.cl.unlock()
        return t.gotMetainfo.C()
index 8ba597e70c566cf4e2d9c8459aa13c536edd4f64..65673539524f9d9bea67ae204a9f78f9ff2da853 100644 (file)
@@ -153,6 +153,22 @@ func (me *trackerScraper) announce(event tracker.AnnounceEvent) (ret trackerAnno
        return
 }
 
+// Returns whether we can shorten the interval, and sets notify to a channel that receives when we
+// might change our mind, or leaves it if we won't.
+func (me *trackerScraper) canIgnoreInterval(notify *<-chan struct{}) bool {
+       gotInfo := me.t.GotInfo()
+       select {
+       case <-gotInfo:
+               // Private trackers really don't like us announcing more than they specify. They're also
+               // tracking us very carefully, so it's best to comply.
+               private := me.t.info.Private
+               return private == nil || !*private
+       default:
+               *notify = gotInfo
+               return false
+       }
+}
+
 func (me *trackerScraper) Run() {
        defer me.announceStopped()
        // make sure first announce is a "started"
@@ -165,7 +181,7 @@ func (me *trackerScraper) Run() {
                me.lastAnnounce = ar
                me.t.cl.unlock()
 
-       wait:
+       recalculate:
                // Make sure we don't announce for at least a minute since the last one.
                interval := ar.Interval
                if interval < time.Minute {
@@ -177,23 +193,26 @@ func (me *trackerScraper) Run() {
                closed := me.t.closed.C()
                me.t.cl.unlock()
 
-               // If we want peers, reduce the interval to the minimum.
+               // If we want peers, reduce the interval to the minimum if it's appropriate.
+
+               // A channel that receives when we should reconsider our interval. Starts as nil since that
+               // never receives.
+               var reconsider <-chan struct{}
                select {
                case <-wantPeers:
-                       if interval > time.Minute {
+                       if interval > time.Minute && me.canIgnoreInterval(&reconsider) {
                                interval = time.Minute
                        }
-                       // Now we're at the minimum, don't trigger on it anymore.
-                       wantPeers = nil
                default:
+                       reconsider = wantPeers
                }
 
                select {
                case <-closed:
                        return
-               case <-wantPeers:
+               case <-reconsider:
                        // Recalculate the interval.
-                       goto wait
+                       goto recalculate
                case <-time.After(time.Until(ar.Completed.Add(interval))):
                }
        }