Closed
Description
When a tracker announce fail, the tracker index get +1 , and cause index out of length error.
panic: runtime error: index out of range [1] with length 1
goroutine 122 [running]:
github.com/cenkalti/rain/internal/tracker.(*Tier).URL(0xc000098f60, 0x16d31dc, 0x10)
/home/runner/work/rain/rain/internal/tracker/tier.go:41 +0x6d
github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).newAnnounceError(0xc0000bde60, 0x1789260, 0xc000419080, 0x0)
/home/runner/work/rain/rain/internal/announcer/periodic.go:343 +0xdc5
github.com/cenkalti/rain/internal/announcer.(*PeriodicalAnnouncer).Run(0xc0000bde60)
/home/runner/work/rain/rain/internal/announcer/periodic.go:190 +0x711
created by github.com/cenkalti/rain/torrent.(*torrent).startNewAnnouncer
/home/runner/work/rain/rain/torrent/torrent_start.go:107 +0x396
In the code /internal/tracker/tier.go, maybe some checks must be done before call CompareAndSwapInt32, index should always <=len(Trackers)-1 。
// Announce a torrent to the tracker.
// If annouce fails, the next announce will be made to the next Tracker in the tier.
func (t *Tier) Announce(ctx context.Context, req AnnounceRequest) (*AnnounceResponse, error) {
index := atomic.LoadInt32(&t.index)
if index >= int32(len(t.Trackers)) {
index = 0
}
resp, err := t.Trackers[index].Announce(ctx, req)
if err != nil {
atomic.CompareAndSwapInt32(&t.index, index, index+1)
}
return resp, err
}
// URL returns the current Tracker in the Tier.
func (t *Tier) URL() string {
return t.Trackers[atomic.LoadInt32(&t.index)].URL()
}