Strictly adher to tracker announce response intervals if a torrent is private

This commit is contained in:
Matt Joiner 2020-12-09 22:36:57 +11:00
parent 65db2436fd
commit c81da2d5ee
2 changed files with 27 additions and 7 deletions

1
t.go
View File

@ -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()

View 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))):
}
}