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