]> Sergey Matveev's repositories - btrtrc.git/blob - tracker/tracker.go
Drop support for go 1.20
[btrtrc.git] / tracker / tracker.go
1 package tracker
2
3 import (
4         "context"
5         "errors"
6         "fmt"
7         "net"
8         "net/http"
9         "net/url"
10         "time"
11
12         "github.com/anacrolix/dht/v2/krpc"
13         "github.com/anacrolix/log"
14
15         trHttp "github.com/anacrolix/torrent/tracker/http"
16         "github.com/anacrolix/torrent/tracker/shared"
17         "github.com/anacrolix/torrent/tracker/udp"
18 )
19
20 const (
21         None      = shared.None
22         Started   = shared.Started
23         Stopped   = shared.Stopped
24         Completed = shared.Completed
25 )
26
27 type AnnounceRequest = udp.AnnounceRequest
28
29 type AnnounceResponse = trHttp.AnnounceResponse
30
31 type Peer = trHttp.Peer
32
33 type AnnounceEvent = udp.AnnounceEvent
34
35 var ErrBadScheme = errors.New("unknown scheme")
36
37 type Announce struct {
38         TrackerUrl          string
39         Request             AnnounceRequest
40         HostHeader          string
41         HttpProxy           func(*http.Request) (*url.URL, error)
42         HttpRequestDirector func(*http.Request) error
43         DialContext         func(ctx context.Context, network, addr string) (net.Conn, error)
44         ListenPacket        func(network, addr string) (net.PacketConn, error)
45         ServerName          string
46         UserAgent           string
47         UdpNetwork          string
48         // If the port is zero, it's assumed to be the same as the Request.Port.
49         ClientIp4 krpc.NodeAddr
50         // If the port is zero, it's assumed to be the same as the Request.Port.
51         ClientIp6 krpc.NodeAddr
52         Context   context.Context
53         Logger    log.Logger
54 }
55
56 // The code *is* the documentation.
57 const DefaultTrackerAnnounceTimeout = 15 * time.Second
58
59 func (me Announce) Do() (res AnnounceResponse, err error) {
60         cl, err := NewClient(me.TrackerUrl, NewClientOpts{
61                 Http: trHttp.NewClientOpts{
62                         Proxy:       me.HttpProxy,
63                         DialContext: me.DialContext,
64                         ServerName:  me.ServerName,
65                 },
66                 UdpNetwork:   me.UdpNetwork,
67                 Logger:       me.Logger.WithContextValue(fmt.Sprintf("tracker client for %q", me.TrackerUrl)),
68                 ListenPacket: me.ListenPacket,
69         })
70         if err != nil {
71                 return
72         }
73         defer cl.Close()
74         if me.Context == nil {
75                 // This is just to maintain the old behaviour that should be a timeout of 15s. Users can
76                 // override it by providing their own Context. See comments elsewhere about longer timeouts
77                 // acting as rate limiting overloaded trackers.
78                 ctx, cancel := context.WithTimeout(context.Background(), DefaultTrackerAnnounceTimeout)
79                 defer cancel()
80                 me.Context = ctx
81         }
82         return cl.Announce(me.Context, me.Request, trHttp.AnnounceOpt{
83                 UserAgent:           me.UserAgent,
84                 HostHeader:          me.HostHeader,
85                 ClientIp4:           me.ClientIp4.IP,
86                 ClientIp6:           me.ClientIp6.IP,
87                 HttpRequestDirector: me.HttpRequestDirector,
88         })
89 }