2
0
mirror of synced 2025-02-22 21:58:24 +00:00
torrent/sources.go
Matt Joiner fdb0911e28
Don't log using torrent source as warning for context cancellation
This probably occurs because the info was obtained and we don't need to try the source anymore.
2023-04-04 19:13:14 +10:00

81 lines
1.8 KiB
Go

package torrent
import (
"context"
"errors"
"fmt"
"net/http"
"github.com/anacrolix/log"
"github.com/anacrolix/torrent/bencode"
"github.com/anacrolix/torrent/metainfo"
)
// Add HTTP endpoints that serve the metainfo. They will be used if the torrent info isn't obtained
// yet. The Client HTTP client is used.
func (t *Torrent) UseSources(sources []string) {
select {
case <-t.Closed():
return
case <-t.GotInfo():
return
default:
}
for _, s := range sources {
_, loaded := t.activeSources.LoadOrStore(s, struct{}{})
if loaded {
continue
}
s := s
go func() {
err := t.useActiveTorrentSource(s)
_, loaded := t.activeSources.LoadAndDelete(s)
if !loaded {
panic(s)
}
level := log.Debug
if err != nil && !errors.Is(err, context.Canceled) {
level = log.Warning
}
t.logger.Levelf(level, "used torrent source %q [err=%v]", s, err)
}()
}
}
func (t *Torrent) useActiveTorrentSource(source string) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
select {
case <-t.GotInfo():
case <-t.Closed():
case <-ctx.Done():
}
cancel()
}()
mi, err := getTorrentSource(ctx, source, t.cl.httpClient)
if err != nil {
return err
}
return t.MergeSpec(TorrentSpecFromMetaInfo(&mi))
}
func getTorrentSource(ctx context.Context, source string, hc *http.Client) (mi metainfo.MetaInfo, err error) {
var req *http.Request
if req, err = http.NewRequestWithContext(ctx, http.MethodGet, source, nil); err != nil {
return
}
var resp *http.Response
if resp, err = hc.Do(req); err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("unexpected response status code: %v", resp.StatusCode)
return
}
err = bencode.NewDecoder(resp.Body).Decode(&mi)
return
}