]> Sergey Matveev's repositories - btrtrc.git/blobdiff - tracker/tracker.go
Drop support for go 1.20
[btrtrc.git] / tracker / tracker.go
index 888228ec04bfc25054a9df58ec55d3331720143e..e96a08a1175e63dc439b4865ae15288b7defbf03 100644 (file)
@@ -1,75 +1,89 @@
 package tracker
 
 import (
+       "context"
        "errors"
+       "fmt"
        "net"
+       "net/http"
        "net/url"
-)
-
-type AnnounceRequest struct {
-       InfoHash   [20]byte
-       PeerId     [20]byte
-       Downloaded int64
-       Left       int64
-       Uploaded   int64
-       Event      AnnounceEvent
-       IPAddress  int32
-       Key        int32
-       NumWant    int32 // How many peer addresses are desired. -1 for default.
-       Port       int16
-} // 82 bytes
-
-type AnnounceResponse struct {
-       Interval int32 // Minimum seconds the local peer should wait before next announce.
-       Leechers int32
-       Seeders  int32
-       Peers    []Peer
-}
+       "time"
 
-type AnnounceEvent int32
+       "github.com/anacrolix/dht/v2/krpc"
+       "github.com/anacrolix/log"
 
-type Peer struct {
-       IP   net.IP
-       Port int
-}
+       trHttp "github.com/anacrolix/torrent/tracker/http"
+       "github.com/anacrolix/torrent/tracker/shared"
+       "github.com/anacrolix/torrent/tracker/udp"
+)
 
 const (
-       None      AnnounceEvent = iota
-       Completed               // The local peer just completed the torrent.
-       Started                 // The local peer has just resumed this torrent.
-       Stopped                 // The local peer is leaving the swarm.
+       None      = shared.None
+       Started   = shared.Started
+       Stopped   = shared.Stopped
+       Completed = shared.Completed
 )
 
-type Client interface {
-       // Returns ErrNotConnected if Connect needs to be called.
-       Announce(*AnnounceRequest) (AnnounceResponse, error)
-       Connect() error
-       String() string
-       URL() string
-}
+type AnnounceRequest = udp.AnnounceRequest
 
-var (
-       ErrNotConnected = errors.New("not connected")
-       ErrBadScheme    = errors.New("unknown scheme")
+type AnnounceResponse = trHttp.AnnounceResponse
 
-       schemes = make(map[string]func(*url.URL) Client)
-)
+type Peer = trHttp.Peer
+
+type AnnounceEvent = udp.AnnounceEvent
 
-func RegisterClientScheme(scheme string, newFunc func(*url.URL) Client) {
-       schemes[scheme] = newFunc
+var ErrBadScheme = errors.New("unknown scheme")
+
+type Announce struct {
+       TrackerUrl          string
+       Request             AnnounceRequest
+       HostHeader          string
+       HttpProxy           func(*http.Request) (*url.URL, error)
+       HttpRequestDirector func(*http.Request) error
+       DialContext         func(ctx context.Context, network, addr string) (net.Conn, error)
+       ListenPacket        func(network, addr string) (net.PacketConn, error)
+       ServerName          string
+       UserAgent           string
+       UdpNetwork          string
+       // If the port is zero, it's assumed to be the same as the Request.Port.
+       ClientIp4 krpc.NodeAddr
+       // If the port is zero, it's assumed to be the same as the Request.Port.
+       ClientIp6 krpc.NodeAddr
+       Context   context.Context
+       Logger    log.Logger
 }
 
-// Returns ErrBadScheme if the tracker scheme isn't recognised.
-func New(rawurl string) (cl Client, err error) {
-       url_s, err := url.Parse(rawurl)
+// The code *is* the documentation.
+const DefaultTrackerAnnounceTimeout = 15 * time.Second
+
+func (me Announce) Do() (res AnnounceResponse, err error) {
+       cl, err := NewClient(me.TrackerUrl, NewClientOpts{
+               Http: trHttp.NewClientOpts{
+                       Proxy:       me.HttpProxy,
+                       DialContext: me.DialContext,
+                       ServerName:  me.ServerName,
+               },
+               UdpNetwork:   me.UdpNetwork,
+               Logger:       me.Logger.WithContextValue(fmt.Sprintf("tracker client for %q", me.TrackerUrl)),
+               ListenPacket: me.ListenPacket,
+       })
        if err != nil {
                return
        }
-       newFunc, ok := schemes[url_s.Scheme]
-       if !ok {
-               err = ErrBadScheme
-               return
+       defer cl.Close()
+       if me.Context == nil {
+               // This is just to maintain the old behaviour that should be a timeout of 15s. Users can
+               // override it by providing their own Context. See comments elsewhere about longer timeouts
+               // acting as rate limiting overloaded trackers.
+               ctx, cancel := context.WithTimeout(context.Background(), DefaultTrackerAnnounceTimeout)
+               defer cancel()
+               me.Context = ctx
        }
-       cl = newFunc(url_s)
-       return
+       return cl.Announce(me.Context, me.Request, trHttp.AnnounceOpt{
+               UserAgent:           me.UserAgent,
+               HostHeader:          me.HostHeader,
+               ClientIp4:           me.ClientIp4.IP,
+               ClientIp6:           me.ClientIp6.IP,
+               HttpRequestDirector: me.HttpRequestDirector,
+       })
 }